ব্লগে ফিরে যান

মডেল ও তুলনাগাইড

আপনার কাজে দুটি LLM ন্যায্যভাবে তুলনা করুন: পক্ষ-পরিবর্তন এবং খরচ লগ

আপনার নিজের টিকিটে দুটি মডেলের মুখোমুখি তুলনা চালান: সমান সেটিংস, প্রতিটি জোড়া উভয় ক্রমে বিচার করা, এবং একটি calls.jsonl লগ যা রানের খরচ দেয়।

CheapTokens Team দ্বারাপ্রকাশিত হয়েছে 14 মিনিট পড়ার সময়

কভার: দুটি মডেল ন্যায্যভাবে তুলনা করুন, একটি তিন-ধাপের প্রবাহ সহ: একই প্রম্পট, পক্ষ পরিবর্তন, প্রতিটি কল লগ করুন
এই পৃষ্ঠায়
  1. একটি পাবলিক টুর্নামেন্ট যা করে এবং আপনি যা ধার করতে পারেন
  2. কাজ: ৩০টি সাপোর্ট টিকিটের উত্তর খসড়া তৈরি
  3. পক্ষ পরিবর্তন করুন: প্রতিটি জোড়া দুবার বিচার করুন
  4. প্রতিটি কল লগ করুন, তারপর রানের মূল্য নির্ধারণ করুন
  5. সম্পূর্ণ রান শুরু করার আগে
  6. নিজেকে বোকা না বানিয়ে ফলাফল পড়া

আপনি দুটি মডেলের মাধ্যমে তিনটি প্রম্পট চালিয়েছেন, এবং দ্বিতীয়টি জিতেছে। এটি বিশ্বাস করার আগে, দেখুন কোনটি দ্বিতীয় স্থানে তালিকাভুক্ত ছিল। একটি ন্যায্য তুলনার জন্য তিনটি জিনিস প্রয়োজন: উভয় মডেলের জন্য অভিন্ন সেটিংস, প্রতিটি জোড়া উভয় ক্রমে বিচার করা, এবং প্রতি কলে টোকেনের লগ, যাতে আপনি জানেন পুরো রানের খরচ কত। নিচে একটি ছোট Python স্ক্রিপ্ট রয়েছে যা আপনার নিজের কাজে এই তিনটিই করে।

একটি পাবলিক টুর্নামেন্ট যা করে এবং আপনি যা ধার করতে পারেন#

Dwarkesh Patel-এর Clocktower Bench একটি অনানুষ্ঠানিক গবেষণা প্রকল্প যেখানে ভাষা মডেলগুলি একে অপরের বিরুদ্ধে Blood on the Clocktower সামাজিক-অনুমান খেলাটি খেলে। এখানে খেলাটি মূল বিষয় নয়; হার্নেসটিই মূল। প্রকল্পের About পৃষ্ঠা অনুসারে (৮ নভেম্বর ২০২৬-এ যাচাই করা), এটি কয়েকটি কাজ করে যা যেকোনো মুখোমুখি তুলনায় থাকা উচিত:

  • একটি মডেল সমস্ত ভালো আসন এবং অন্যটি সমস্ত খারাপ আসন খেলে, এবং প্রতিটি ডিল পক্ষ পরিবর্তন করে দুবার খেলা হয়, যাতে একটি ভাগ্যবান আসন ফলাফল নির্ধারণ না করে;
  • সমস্ত মডেল একই সেটিংস পায়: একই যুক্তি প্রচেষ্টা, প্রতি পালায় ৮,০০০-টোকেন সীমা এবং বক্তৃতায় ১৫০-শব্দের সীমা;
  • Storyteller স্ক্রিপ্টেড, তাই কোনো মডেল খেলাটি পরিচালনা করে না;
  • প্রতিটি API কল তার টোকেন এবং খরচ সহ calls.jsonl-এ লেখা হয়। পৃষ্ঠাটি বলে যে একটি একক খেলা প্রায় $2 থেকে $50 পর্যন্ত খরচ করে, মডেলের উপর নির্ভর করে (OpenAI এবং Anthropic API-তে)।

হার্নেসটি OpenAI এবং Anthropic মডেলের জন্য তৈরি, এবং আপনার কাজ সম্ভবত একটি বোর্ড গেম নয়। কিন্তু তিনটি অভ্যাস স্থানান্তরযোগ্য: সমান সেটিংস, পক্ষ পরিবর্তন, এবং একটি খরচ লগ। এই গাইডের বাকি অংশ সেগুলি একটি সাধারণ কাজে প্রয়োগ করে।

প্রতিটি টিকিট উভয় মডেলের কাছে যায়; বিচারক জোড়াটি দুবার, বিপরীত ক্রমে দেখে
একটি টিকিটের জন্য পক্ষ-পরিবর্তন লুপ

কাজ: ৩০টি সাপোর্ট টিকিটের উত্তর খসড়া তৈরি#

ধরুন আপনি একটি ছোট সাপোর্ট ডেস্ক চালান এবং জানতে চান DeepSeek-V4-Flash নাকি GLM-5.3-Flash ভালো প্রথম খসড়া লেখে। আপনার কাছে tickets.jsonl ফাইল আছে যাতে ৩০টি বাস্তব টিকিট রয়েছে, প্রতি লাইনে একটি JSON অবজেক্ট: {"id": 1, "text": "..."}।

APIটি OpenAI-সামঞ্জস্যপূর্ণ, তাই অফিসিয়াল openai প্যাকেজটি https://api.cheaptokens.dev/v1-এ CheapTokens-এর সাথে কাজ করে। ডক্স থেকে সম্পূর্ণ মডেল আইডি ব্যবহার করুন: deepseek-ai/DeepSeek-V4-Flash-0731 এবং zai-org/GLM-5.3-Flash। উভয় মডেল একটি তৃতীয় মডেলকে বিচারক হিসেবে পায়, MiniMaxAI/MiniMax-M2.7, যাতে কোনো প্রতিযোগী নিজের কাজের মূল্যায়ন না করে।

লগ সম্ভব করে তোলে এমন অংশ দিয়ে শুরু করুন: একটি ফাংশন যার মধ্য দিয়ে প্রতিটি কল যায়।

python
import json, os, re
from openai import OpenAI

client = OpenAI(base_url="https://api.cheaptokens.dev/v1",
                api_key=os.environ["CHEAPTOKENS_API_KEY"])

CONTESTANTS = {"deepseek": "deepseek-ai/DeepSeek-V4-Flash-0731",
               "glm": "zai-org/GLM-5.3-Flash"}
JUDGE = "MiniMaxAI/MiniMax-M2.7"
SETTINGS = {"temperature": 0.2, "max_tokens": 800}   # same for both

def call(model, messages, role, ticket_id, **settings):
    r = client.chat.completions.create(model=model, messages=messages, **settings)
    with open("calls.jsonl", "a", encoding="utf-8") as f:
        f.write(json.dumps({
            "role": role, "ticket": ticket_id, "model": model,
            "input_tokens": r.usage.prompt_tokens,
            "output_tokens": r.usage.completion_tokens,
            "finish": r.choices[0].finish_reason}) + "\n")
    return r.choices[0].message.content or ""

def draft(model, ticket):
    msgs = [{"role": "system", "content": "You answer support tickets. "
             "Reply in under 80 words, politely, with no promises about refunds."},
            {"role": "user", "content": ticket["text"]}]
    return call(model, msgs, "draft", ticket["id"], **SETTINGS)

calls.jsonl-এর ক্ষেত্রগুলি এই স্ক্রিপ্টটি বেছে নেয়; ব্যবহারের সংখ্যাগুলি API প্রতিক্রিয়ার usage অবজেক্ট থেকে আসে। উভয় মডেল একই সিস্টেম প্রম্পট, একই temperature এবং একই max_tokens পায়। একটি মডেলের জন্য এগুলির একটি পরিবর্তন করুন এবং আপনি সেটিংসের তুলনা করছেন, মডেলের নয়।

পক্ষ পরিবর্তন করুন: প্রতিটি জোড়া দুবার বিচার করুন#

এখন বিচারক। একটি বিচারক মডেল একটি নির্দিষ্ট স্লটে উত্তর দিকে ঝুঁকতে পারে, তাই একটি একক রায় গুণমানের সাথে অবস্থান মিশ্রিত করে। Clocktower কৌশলটি সুন্দরভাবে মানানসই: প্রতিটি জোড়া উভয় ভূমিকায় দেখান। একটি উত্তর একটি টিকিট জেতে শুধুমাত্র যদি বিচারক উভয় ক্রমে এটি বেছে নেয়। যদি রায় উত্তরটির পরিবর্তে স্লট অনুসরণ করে, টিকিটটি একটি টাই।

python
def judge(ticket, first, second):
    prompt = (f"Ticket:\n{ticket['text']}\n\nReply A:\n{first}\n\nReply B:\n{second}\n\n"
              "Which reply is better for the customer? Finish with a last line: Verdict: A or Verdict: B.")
    out = call(JUDGE, [{"role": "user", "content": prompt}], "judge",
               ticket["id"], temperature=0, max_tokens=1000)
    letters = re.findall(r"Verdict:\s*([AB])\b", out)
    return letters[-1] if letters else None

tickets = [json.loads(l) for l in open("tickets.jsonl", encoding="utf-8")]
wins = {"deepseek": 0, "glm": 0, "tie": 0}

for t in tickets:
    a = draft(CONTESTANTS["deepseek"], t)
    b = draft(CONTESTANTS["glm"], t)
    v1 = judge(t, a, b)   # DeepSeek's reply shown as A
    v2 = judge(t, b, a)   # GLM's reply shown as A
    pick1 = {"A": "deepseek", "B": "glm"}.get(v1)
    pick2 = {"A": "glm", "B": "deepseek"}.get(v2)
    wins[pick1 if pick1 and pick1 == pick2 else "tie"] += 1

print(wins)

দুটি বিবরণ সহজে মিস করা যায়। বিচারক temperature=0-এ চলে যাতে তার রায়গুলি আরও স্থির থাকে; প্রতিটি মডেল সেই সেটিংকে সম্মান করে না, তাই কয়েকটি জোড়া পুনরায় চালান এবং রায়গুলি বিশ্বাস করার আগে তুলনা করুন। রায় শুধুমাত্র একটি চূড়ান্ত Verdict: লাইন থেকে পড়া হয়, এবং সীমাগুলি উদার (খসড়ার জন্য ৮০০, বিচারকের জন্য ১০০০) যাতে উত্তর দেওয়ার আগে যুক্তি করে এমন একটি মডেল চিন্তার মাঝপথে কেটে না যায়; নিচের অনুমানটি সাধারণ আকার ব্যবহার করে, সীমা নয়। একটি অপার্সেবল উত্তর None দেয়, যা রান ক্র্যাশ করার পরিবর্তে একটি টাইতে পড়ে।

নিজে চেষ্টা করুনচেষ্টা করুন: বিচারক টিকিট ৭-এর জন্য উভয় ক্রমে "A" বলেছেন। সেই টিকিটে কে জিতবে?উত্তর দেখান

কেউ না। প্রথম ক্রমে A ছিল DeepSeek-এর উত্তর, দ্বিতীয় ক্রমে A ছিল GLM-এর উত্তর, তাই বিচারক স্লট পছন্দ করেছেন, মডেল নয়। কোডটি এটিকে টাই হিসেবে গণনা করে। এই ধরনের টাইয়ের স্তূপ নিজেই একটি ফলাফল: আপনার কাজে দুটি মডেল কাছাকাছি, অথবা আপনার বিচারক প্রম্পট খুব অস্পষ্ট।

ক্রম একটি পরীক্ষাকে ঝুঁকানোর একটি উপায় মাত্র। সেটিংস, প্রম্পট এবং লগিংও এটি ঝুঁকাতে পারে, তাই শুধু কে প্রথমে যায় তা নয়, পুরো সেটআপ পরীক্ষা করুন। এখানে একই পরীক্ষা আগে এবং পরে।

তুলনা করুন

যখন আপনি নৈমিত্তিক তুলনা বন্ধ করেন তখন কী পরিবর্তন হয়

নৈমিত্তিক

প্রতি মডেলে একটি প্রম্পট, ডিফল্ট চালু রাখা, জোড়াটি একটি ক্রমে দেখানো, এবং মাসের শেষে ড্যাশবোর্ড থেকে বিল পড়া। বিজয়ী সেই মডেল হতে পারে যেটি প্রথমে তালিকাভুক্ত হয়েছিল।

ন্যায্য

একটি শেয়ার করা সিস্টেম প্রম্পট এবং একই temperature এবং max_tokens, প্রতিটি জোড়া উভয় ক্রমে বিচার করা, এবং প্রতিটি কলের জন্য calls.jsonl-এ একটি লাইন। বিজয়ী সেই ব্যক্তি যে উভয় আসন থেকে জেতে।

প্রতিটি কল লগ করুন, তারপর রানের মূল্য নির্ধারণ করুন#

লগই তুলনাটিকে বাজেটে পরিণত করে। রানের পরে, প্রতি মডেলে টোকেন যোগ করুন:

python
from collections import defaultdict

totals = defaultdict(lambda: [0, 0, 0])
for line in open("calls.jsonl", encoding="utf-8"):
    c = json.loads(line)
    s = totals[c["model"]]
    s[0] += c["input_tokens"]; s[1] += c["output_tokens"]; s[2] += 1

for model, (tin, tout, n) in totals.items():
    print(model, n, "calls", tin, "input", tout, "output")

আপনি প্রতি মডেলে একটি লাইন পাবেন যাতে কল সংখ্যা, ইনপুট টোকেন এবং আউটপুট টোকেন থাকে। মডেলের দুটি মূল্য (ইনপুট এবং আউটপুট আলাদাভাবে বিল করা হয়) দিয়ে গুণ করুন বা, আরও সহজ, মোটগুলি একটি লাইভ খরচ মার্কারে পেস্ট করুন।

আপনি চালানোর আগেও অনুমান করতে পারেন। ধরে নিন প্রতিটি টিকিট প্লাস সিস্টেম প্রম্পট প্রায় ৩০০ ইনপুট টোকেন, একটি খসড়া প্রায় ২৫০ আউটপুট টোকেন, এবং বিচারক প্রায় ৮০০ ইনপুট টোকেন দেখে (টিকিট প্লাস উভয় উত্তর প্লাস প্রশ্ন) এবং প্রায় ২০০ টোকেন দিয়ে উত্তর দেয় (রায় লাইন প্লাস চিন্তা করার জন্য একটু জায়গা):

  • খসড়া: ৩০ টিকিট × ২ মডেল = ৬০ কল, প্রতি প্রতিযোগীর জন্য ৩০ × ৩০০ = ৯০০০ ইনপুট এবং ৩০ × ২৫০ = ৭৫০০ আউটপুট টোকেন;
  • রায়: ৩০ টিকিট × ২ ক্রম = ৬০ কল, বিচারকের উপর ৬০ × ৮০০ = ৪৮০০০ ইনপুট এবং ৬০ × ২০০ = ১২০০০ আউটপুট টোকেন।

বর্তমান মূল্যে, একজন প্রতিযোগীর ৩০টি খসড়ার খরচ DeepSeek-V4-Flash-এ $0.00089 এবং GLM-5.3-Flash-এ $0.00048। MiniMax-M2.7-এ ৬০টি রায়ের খরচ $0.0042। তিনটি যোগ করুন এবং একটি অনুরোধ পাঠানোর আগেই পুরো তুলনার মূল্য পেয়ে যাবেন। একই খসড়া কাজের চাপ তিনটি মডেল জুড়ে, ইনপুট এবং আউটপুট একসাথে গণনা করা:

মডেল খরচ OpenRouter
GLM-5.3-Flash $0.00048 $0.00092
DeepSeek-V4-Flash $0.00089 $0.0017
MiniMax-M2.7 $0.0016 $0.0189

মোট ৯,০০০ ইনপুট এবং ৭,৫০০ আউটপুট টোকেন। প্রতি 1M টোকেনের দাম বর্তমান এবং আমাদের ট্যারিফের সাথে পরিবর্তিত হয়; OpenRouter কলামটি একই ওয়ার্কলোডের জন্য রেফারেন্স মূল্য দেখায়।

টেবিলটি OpenRouter রেফারেন্সও দেখায়, যাতে আপনি দেখতে পারেন মোটটি কীভাবে তুলনা করে। টোকেন অনুমানগুলি আপনার পরিবর্তন করার জন্য: যদি আপনার টিকিটগুলি দীর্ঘ হয়, বিচারক ইনপুট দ্রুততম বৃদ্ধি পায়, কারণ এটি উভয় উত্তর দুবার বহন করে। যদি আপনার বিচারক উত্তর দেওয়ার আগে জোরে চিন্তা করে, তার আউটপুট সংখ্যাও বাড়ে, এবং আপনার লগ এটি দেখাবে। একটি অনুরোধের আগে টোকেন গণনার অভ্যাসের জন্য, দেখুন একটি অনুরোধ পাঠানোর আগে টোকেন গণনা করুন।

Clocktower যে একই সীমা ব্যবহার করে তা চুরি করার যোগ্য। এটি প্রতি পালায় ৮,০০০ টোকেন সেট করে, এবং আপনার কাছে ইতিমধ্যে max_tokens আছে। এটি SETTINGS-এ রাখুন এবং একটি অনিয়ন্ত্রিত উত্তর চুপচাপ আপনার অনুমানকে গুণ করতে পারবে না।

সম্পূর্ণ রান শুরু করার আগে#

চেকলিস্ট

একটি ন্যায্য তুলনার জন্য প্রি-ফ্লাইট

শেষ আইটেমটি গুরুত্বপূর্ণ। তিনটি টিকিট চালান, calls.jsonl খুলুন এবং পড়ুন। পরীক্ষা করুন যে finish stop বলে length-এর পরিবর্তে; যদি একটি খসড়া max_tokens দ্বারা কেটে যায়, একটি মডেল শুধুমাত্র তার উত্তর ছেঁটে ফেলার কারণে হারতে পারে। বিচারকের কলগুলির ক্ষেত্রেও একই কথা: সেখানে একটি length একটি নীরব টাইতে পরিণত হয়, তাই None রায়গুলিও গণনা করুন। যদি আপনার কাজের একটি একক সঠিক উত্তর থাকে, আপনার আদৌ বিচারকের প্রয়োজন নাও হতে পারে: সঠিক-মিল গ্রেডিং দিয়ে ২০টি ক্ষেত্রে আপনার প্রম্পট পরীক্ষা করুন।

নিজেকে বোকা না বানিয়ে ফলাফল পড়া#

wins-এ তিনটি সংখ্যা দেখুন। ত্রিশটি টিকিট একটি ছোট নমুনা: ১২ থেকে ৯-এ ৯টি টাইয়ের মতো একটি বিভাজন আপনাকে বলে যে মডেলগুলি কাছাকাছি, একটি অন্যটির চেয়ে ভালো নয়। লগ এখানে সাহায্য করে। যদি একটি মডেল সামান্য জেতে কিন্তু অনেক বেশি আউটপুট ব্যবহার করে, আসল প্রশ্নটি কাজের মূল্য, জয়ের সংখ্যা নয়; প্রতি ১M টোকেনের মূল্য বনাম প্রতি কাজের খরচ সেই তুলনার মধ্য দিয়ে যায়।

যদি ফলাফল কাছাকাছি হয়, কাজের জন্য সস্তা মডেল বেছে নিন, অথবা আরও টিকিট যোগ করুন এবং পুনরায় চালান। উভয়ই চেষ্টা করা সস্তা কারণ পুরো যন্ত্রপাতি ইতিমধ্যে একটি লুপ। যখন আপনি অন্য মডেলে অনুশীলনটি পুনরাবৃত্তি করতে চান, উপরের তিনটি মডেল একটি API এবং একটি কী-এর পিছনে বসে: ডক্স-এ সেটআপ প্রতিটির জন্য একই, এবং মূল্য পৃষ্ঠা তালিকা করে প্রতিটির এখন কী খরচ হয়। OpenAI বনাম Anthropic মডেলের উপর Dwarkesh Patel-এর নিজস্ব আবিষ্কার (সনাক্তকরণ বনাম প্রতারণা) তার খেলার জন্য তার ফলাফল; আপনার আপনার টিকিট থেকে আসবে।