مواد پر جائیں
19/30باب 19 از 30

Production میں RAG: chunking، retrieval اور دیانت دار citations

512 حروف پر blind cut سے 32 میں سے 4 جواب retriever سے پہلے مر جاتے ہیں۔ صرف chunker درست کریں تو rank 115 سے 3 ہو جاتا ہے۔

اس صفحے پر

یہ ایک حقیقی assistant کے ایک حقیقی user کا حقیقی سوال ہے: میرے eval set میں 20 items ہیں، کیا score پر اعتماد کرنے کے لیے یہ کافی ہے۔ corpus میں جواب موجود ہے — اس کا پورا ایک section۔ یہ وہ چار fragments ہیں جو retriever نے واقعی prompt میں ڈالے۔

four fragments, chunked blind at 512 charactersTEXT
[1] d=0.578  ship — that set has been used for fitting, and its score stops being
             unbiased. Measured on this belt: sweeping the threshold on the
             validation set picks 0.196, and the model then scores F1 = 0.4122…

[2] d=0.602  ng when the model is confidently **wrong**. Evaluate both at a few
             scores, for an example whose true label is 1: | score | p | …

[3] d=0.613  ard and watch both numbers: | | reward model's score | true quality
             | length produced | … The reward went up by a factor of 2.5. The…

[4] d=0.617  | 0.6 | +0.97 | +1.00 | +0.27 | … The reward model is working
             perfectly. It has faithfully learned the preferences it was shown…

چار میں سے تین mid-word شروع ہوتے ہیں۔ دو ایک مختلف subject کے مختلف chapter سے ہیں۔ اور وہ fragment جو سوال کا جواب دیتا ہے — جس میں Seventeen out of twenty cannot distinguish an 85 % model from a 65 % one موجود ہے — rank 115 پر واپس آیا۔

اب وہی سوال، وہی embedding model، وہی prompt template۔ ایک چیز بدلی: documents کو کیسے کاٹا گیا۔

four fragments, cut on section boundaries with a contextual headerTEXT
[1] d=0.594  [Classification, Cross-Entropy… > How many test examples do I need?]
             Read it backwards, which is how you will use it: ±5 points needs
             about 200 examples. ±2 points needs about 1,230…

[2] d=0.598  [Classification, Cross-Entropy… > Three splits, and the leak…]
             Why three splits and not two? Because the moment you use a set of
             examples to *choose* anything…

[3] d=0.600  [Classification, Cross-Entropy… > How many test examples do I need?]
             The honest reading of 17/20 is *somewhere between 64 % and 95 %*.
             …Seventeen out of twenty cannot distinguish an 85 % model from a 65 % one.

[4] d=0.605  [Classification, Cross-Entropy… > How many test examples do I need?]
             Suppose you score a model on 20 examples and it gets 17 right. You
             report 85 %. …Wilson 95% CI : [0.6396, 0.9476]

Rank 115 سے rank 3۔ کسی نے model، prompt، threshold یا slots کی تعداد کو ہاتھ نہیں لگایا۔ یہ chapter اسی فرق کے بارے میں ہے، اور ان چار دوسری جگہوں کے بارے میں بھی جہاں retrieval system خاموشی سے آپ سے جھوٹ بولتا ہے۔

تفصیلات دکھائیں

اس chapter کو پچھلے chapters سے کیا چاہیے، اور وہ ایک جگہ جہاں یہ زبان بدلتا ہے۔

  • باب 1 نے dot product اور L2 norm کی تعریف کی۔ نیچے threshold والا section وہی دو چیزیں ہے، اور کچھ نہیں۔
  • باب 8 نے language model کی embedding table کو ایک retrieval embedding model سے الگ کیا جو pairs پر contrastively trained تھا، cosine similarity ناپی، اور اس وعدے پر ختم ہوا کہ Chapter 19 ایک concrete cut-off تک پہنچے گا۔ وہ وعدہ یہاں پورا ہوتا ہے۔ اس میں سے کچھ بھی دہرایا نہیں گیا۔
  • باب 4 نے Wilson interval بنایا؛ باب 15 نے evaluation harness بنایا۔ نیچے ہر table پہلا ساتھ رکھتی ہے اور دوسرے نے اسے پیدا کیا۔
  • باب 16 نے context window کی قیمت لگائی۔ اس chapter کے آخر میں assembled prompt کی لاگت 591 tokens ہے، اور یہی وہ budget ہے جس کے لیے fragments مقابلہ کرتے ہیں۔

یہاں سب کچھ TypeScript ہے، جیسا کہ باب 14 سے ہے، اور یہ وہ chapter ہے جہاں rule اپنی کمائی کرتا ہے: ingestion queues اور storage ہے، search ایک network call ہے، اور citations کے ساتھ prompt assemble کرنا server کا کام ہے۔ measurement عمداً وہی code ہے جس کے گرد scoreboard لگایا گیا ہے — ایک دوسرے implementation سے scored retriever اس software کے بارے میں number ہے جسے آپ ship نہیں کر رہے، اور نیچے cosine threshold صرف اس لیے قابلِ یقین ہے کہ آپ اسے اسی chunker سے sweep ہوتے دیکھتے ہیں جو production میں چلے گا۔

نیچے سب کچھ ایک corpus کے خلاف measured ہے: اس course کے پہلے تیرہ chapters — 13 documents، 359,067 characters، 127 sections، front matter اور bibliographies نکالی ہوئی۔ یہ ایک حقیقی technical corpus ہے، جس میں prose، tables، formulas اور code blocks ہیں، اور یہ بالکل اسی قسم کی چیز ہے جسے لوگ knowledge base میں load کرتے ہیں اور پھر شکایت کرتے ہیں۔

Ground truth 32 questions ہے، ہر ایک کے ساتھ ایک needle: corpus سے ایک مختصر verbatim sentence جو اس کا جواب دیتی ہے۔ ہر needle 359,067 characters میں ٹھیک ایک بار آتی ہے، اور کوئی بھی section heading نہیں — یہ check اہم ہے، کیونکہ ایسا chunker جو headings کو ہر chunk میں copy کرے ورنہ خود کو score کر لے گا۔ ہر question دو بار پوچھا گیا ہے، ایک بار course English میں اور ایک بار اس طرح جیسے support ticket اسے لکھتی ہے: 32 ground truths پر 64 queries۔

Retrieval تب correct ہے جب returned chunk needle کو مکمل contain کرے۔ یہی واحد definition ہے جو generator کی ضرورت سے match کرتی ہے: prompt میں آدھی sentence جواب نہیں، hazard ہے۔

embedding model all-MiniLM-L6-v2 ہے — 384 dimensions، mean-pooled اور normalised، وہ contrastively trained model جسے Chapter 8 نے measured کیا تھا۔ corpus کو index کرنے میں CPU پر 20.8 seconds لگتے ہیں، 22 ms per chunk؛ ایک query کی embedding میں 13 ms لگتے ہیں۔

تین independent ingredients سے چھ strategies۔ Blind text کو دیکھے بغیر ہر 512 characters پر cuts کرتا ہے۔ Boundaries paragraph کے اندر کبھی cut نہیں کرتا، صرف جب ایک paragraph budget سے زیادہ ہو تو sentence boundary پر fallback کرتا ہے۔ Header ہر chunk کے آگے اس کے document title اور section path کو prefix کرتا ہے۔ Overlap previous chunk کے آخری 64 characters کو next میں copy کرتا ہے۔

strategychunksanswers destroyedR@1R@4R@8R@20MRR
A blind 5127084 / 320.1250.2970.4220.5940.241
B blind + overlap80900.1720.3910.4530.6250.286
C boundaries94000.1560.4220.5310.6720.293
D boundaries + overlap94000.1560.3590.5160.6560.277
E boundaries + header94000.0940.4220.5780.8280.280
F boundaries + header + overlap94000.1560.3910.5620.7660.298

64 queries کے ساتھ R@20 پر 95 % Wilson interval A کے لیے [0.471, 0.705] اور E کے لیے [0.718, 0.901] ہے — یہ overlap نہیں کرتے، مگر باقی اکثر columns کرتے ہیں، اور unpaired table انہیں الگ نہیں کر سکتی۔ ہر strategy انہی queries کا جواب دیتی ہے، اس لیے honest test paired ہے: ہر strategy کی wins اور losses دوسری کے مقابل count کریں اور discordant pairs پر sign test چلائیں۔ تین results اس سے بچتے ہیں۔

Blind chunking بتیس میں سے چار answers کو outright destroy کر دیتی ہے۔ انہیں صرف badly rank نہیں کرتی — destroy کرتی ہے۔ needle 512-character boundary کے آر پار ہے، اس لیے index میں کوئی chunk اسے contain نہیں کرتا، اور ان queries کے لیے recall ceiling zero ہے۔ کوئی reranker انہیں recover نہیں کرتا، کوئی threshold مدد نہیں کرتا، کوئی larger model مدد نہیں کرتا۔ آپ ایسا text retrieve نہیں کر سکتے جو آپ کے index میں کہیں ایک ٹکڑے میں موجود ہی نہ ہو۔ یہ RAG میں سب سے کم report ہونے والی failure ہے، کیونکہ یہ بالکل bad retriever جیسی نظر آتی ہے۔

Overlap اسے fix کرتا ہے اور کچھ نہیں۔ overlap والی ہر strategy zero answers lose کرتی ہے، overlap اسی لیے ہے۔ یہ ranking improve نہیں کرتا: R@8 پر B against A +8/−6، p = 0.79 ہے؛ R@20 پر +9/−7، p = 0.80 ہے۔ اس سے بھی worse، header کے اوپر overlap add کرنا actively hurt کرتا ہے — F against E R@20 پر +2/−6 ہے — اور وجہ mechanical ہے۔ chunk کا vector اس کے tokens پر mean ہوتا ہے، اس لیے previous chunk کے 64 characters اس mean کو neighbour کے topic کی طرف drag کرتے ہیں۔ Overlap split answer کے خلاف insurance ہے، precision میں ادا کی گئی قیمت کے ساتھ۔

Contextual header ہی retrieval خریدتا ہے۔ E against A +18/−3 at R@20, p = 0.0015 ہے۔ اور ablation کہتا ہے boundaries یہ کام نہیں کر رہیں: E against C — same cuts، header ہی واحد difference — +12/−2, p = 0.0129 ہے۔ paragraph کے آگے “Classification, Cross-Entropy, and How Not to Fool Yourself > How many test examples do I need?” prefix کرنا embedding model کو بتاتا ہے کہ paragraph کس بارے میں ہے، جو paragraph خود اکثر نہیں کہتا۔ یہ documents کے لیے pronoun resolver ہے۔

یہ chunker کو اس کی shape دیتا ہے، اور ایک rule جو غلط کرنا آسان ہے:

chunk.tsTS
export interface Chunked {
  /** What gets EMBEDDED: contextual header + this chunk's own content. */
  text: string;              
  /** ONLY this chunk's own content: what is quoted back to the user. */
  content: string;           
  section: string;
  /** Character range in the document's canonical text. Sliceable. */
  from: number;
  to: number;
}

export function chunkDocument(doc: string, docTitle: string, target = 512): Chunked[] {
  const out: Chunked[] = [];
  const heads = [...doc.matchAll(/^## (.+)$/gm)].map((m) => ({ at: m.index!, title: m[1].trim() }));
  const spans = heads.length
    ? heads.map((h, i) => ({ ...h, end: i + 1 < heads.length ? heads[i + 1].at : doc.length }))
    : [{ at: 0, title: "", end: doc.length }];

  for (const s of spans) {
    const header = s.title ? `${docTitle} > ${s.title}` : docTitle;     
    const skip = /^## .+\n/.exec(doc.slice(s.at, s.end))?.[0].length ?? 0;
    const body = doc.slice(s.at + skip, s.end);
    const origin = s.at + skip;

    // The offset is FOUND in the document, never accumulated: adding up
    // lengths drifts by a character wherever a separator was normalised,
    // and a citation anchor off by one points at the wrong line.
    const emit = (from: number, to: number) => {
      const raw = body.slice(from, to);
      const lead = raw.length - raw.trimStart().length;
      const content = raw.trim();
      if (!content) return;
      out.push({ text: `[${header}]\n${content}`, content, section: s.title,
                 from: origin + from + lead, to: origin + from + lead + content.length });
    };

    let open: [number, number] | null = null;
    for (const m of body.matchAll(/[^\n]([^\n]|\n(?!\n))*/g)) {          // paragraphs
      const [pf, pt] = [m.index!, m.index! + m[0].length];
      if (pt - pf > target) {                                            // one huge paragraph
        if (open) { emit(open[0], open[1]); open = null; }
        let cur: [number, number] | null = null;
        for (const sm of body.slice(pf, pt).matchAll(/[^.!?]*[.!?]*\s*/g)) {
          if (!sm[0]) continue;
          const [sf, st] = [pf + sm.index!, pf + sm.index! + sm[0].length];
          if (cur && st - cur[0] > target) { emit(cur[0], cur[1]); cur = null; }
          cur = cur ? [cur[0], st] : [sf, st];
        }
        if (cur) emit(cur[0], cur[1]);
        continue;
      }
      if (open && pt - open[0] > target) { emit(open[0], open[1]); open = null; }
      open = open ? [open[0], pt] : [pf, pt];
    }
    if (open) emit(open[0], open[1]);
  }
  return out;
}

دو texts، ایک نہیں۔ text وہ ہے جو embedded ہوتا ہے، header سمیت۔ content صرف اس chunk کے اپنے words ہیں، اور یہی user کو quote کیے جاتے ہیں۔ text quote کریں تو citation ایک ایسا header دکھاتی ہے جو document میں اس point پر موجود نہیں — اور overlap کے ساتھ، previous fragment سے تعلق رکھنے والی repeated tail بھی۔ پھر یہ ایسا text display کرتی ہے جو وہاں نہیں ہے جہاں یہ کہتی ہے، جو کچھ نہ دکھانے سے بھی بدتر ہے۔

Header free نہیں ہے۔ 940 chunks میں یہ index کے 114,275 embedded tokens میں سے 24,213 tokens لیتا ہے: جو embed کرنے کے لیے آپ pay کرتے ہیں اس کا 21.2 % ایک header ہے جو آپ نے خود لکھا۔ یہ chunks کو encoder کی window کے against بھی دھکیلتا ہے۔ all-MiniLM-L6-v2 256 word-pieces accept کرتا ہے؛ strategy E میں 17 chunks اس line سے اوپر ہیں اور F میں 28، ہر ایک silently truncate ہوا، کسی چیز کی طرف سے کوئی warning نہیں۔ آپ کا effective chunk size آپ کی config کا number نہیں — یہ اس number اور encoder کی window میں سے چھوٹا ہے۔

BM25 کی بیس lines، جنہیں سب skip کرتے ہیں

اس حصے کا لنک: BM25 کی بیس lines، جنہیں سب skip کرتے ہیں

Dense retrieval کی ایک systematic weakness ہے اور وہ subtle نہیں: یہ meaning match کرتی ہے، اس لیے آپ نے exactly کون سی string type کی اس سے بے پروا ہے۔ part number، error code، acronym، surname — کسی کے پاس embed کرنے کے لیے useful meaning نہیں، اور error code کا nearest neighbour آپ کے corpus کا ہر دوسرا error code ہے۔

Classical answer اس سب سے پرانا ہے اور بیس lines لیتا ہے۔ BM25 document کو اس بنیاد پر score کرتا ہے کہ query کے terms اس میں کتنی بار آتے ہیں، ہر term کو اس کی frequency بڑھنے پر damp کرتا ہے اور long documents کو punish کرتا ہے جو محض length سے matches جمع کر لیتے ہیں۔1 Term tt contribute کرتا ہے

idf(t)ft,d(k1+1)ft,d+k1(1b+bdd)\mathrm{idf}(t)\cdot\frac{f_{t,d}\,(k_1+1)}{f_{t,d} + k_1\left(1 - b + b\,\frac{|d|}{\overline{|d|}}\right)}

جہاں ft,df_{t,d} document میں term کا count ہے، d|d| اس کی length، d\overline{|d|} average length، اور k1=1.2k_1 = 1.2 اور b=0.75b = 0.75 دو conventional constants — k1k_1 یہ set کرتا ہے کہ repetition کتنی تیزی سے مدد کرنا چھوڑتا ہے، bb length کو کتنی سختی سے punish کیا جاتا ہے۔

bm25.tsTS
const toks = (s: string) => s.toLowerCase().match(/[a-z0-9]+/g) ?? [];

export class BM25 {
  private tf: Map<string, number>[] = [];
  private len: number[] = [];
  private idf = new Map<string, number>();
  private avg = 0;
  private k1: number; private b: number;
  constructor(docs: string[], k1 = 1.2, b = 0.75) {
    this.k1 = k1; this.b = b;
    const df = new Map<string, number>();
    for (const d of docs) {
      const t = new Map<string, number>(); const ws = toks(d);
      for (const w of ws) t.set(w, (t.get(w) ?? 0) + 1);
      for (const w of t.keys()) df.set(w, (df.get(w) ?? 0) + 1);
      this.tf.push(t); this.len.push(ws.length);
    }
    this.avg = this.len.reduce((a, b) => a + b, 0) / this.len.length;
    const N = docs.length;
    for (const [w, n] of df) this.idf.set(w, Math.log(1 + (N - n + 0.5) / (n + 0.5)));
  }
  scores(query: string): number[] {
    const q = toks(query);
    return this.tf.map((tf, i) => {
      const L = this.len[i]; let s = 0;
      for (const w of q) {
        const f = tf.get(w); if (!f) continue;
        s += (this.idf.get(w) ?? 0) * (f * (this.k1 + 1)) /
             (f + this.k1 * (1 - this.b + (this.b * L) / this.avg));
      }
      return s;
    });
  }
}

940 chunks پر یہ query کو 1.14 ms میں score کرتا ہے، دو hash maps کے علاوہ کوئی index نہیں۔ اور یہ museum piece نہیں:

retrieverR@1R@4R@8MRRcost per query
dense (cosine)0.0940.4220.5780.280embed کرنے کے لیے 13 ms + scan کے لیے 0.3 ms
lexical (BM25)0.2190.3750.4690.3131.14 ms
hybrid (RRF)0.2030.4840.6090.346دونوں
hybrid + cross-encoder0.3120.5780.7030.447+ 569 ms

BM25 اس corpus پر dense retriever کی top-1 accuracy کو double سے زیادہ کر دیتا ہے، اور rank 8 تک اس سے بری طرح ہار جاتا ہے۔ وہ different queries پر fail ہوتے ہیں، اور دونوں چلانے کی پوری دلیل یہی ہے۔

انہیں fuse کرنے میں obvious approach غلط ہے۔ Cosine distances اور BM25 scores ایک ہی scale پر نہیں، ایک ہی طرح bounded نہیں، اور انہیں per query normalise کرنے سے weight اس پر depend کرتا ہے کہ best hit اتفاقاً کتنا اچھا تھا۔ Reciprocal rank fusion scores پھینک دیتا ہے اور صرف ranks رکھتا ہے:2

RRF(d)=lists1k+rank(d),k=60\mathrm{RRF}(d) = \sum_{\text{lists}} \frac{1}{k + \mathrm{rank}(d)}, \qquad k = 60
retrieve.tsTS
/** Reciprocal rank fusion: ranks, not scores. Nothing to calibrate. */
export function rrf(lists: number[][], k = 60): number[] {
  const acc = new Map<number, number>();
  for (const list of lists)
    list.forEach((id, r) => acc.set(id, (acc.get(id) ?? 0) + 1 / (k + r + 1)));
  return [...acc.entries()].sort((a, b) => b[1] - a[1]).map(([id]) => id);
}

اور یہاں table کی honest reading table سے زیادہ اہم ہے۔ Hybrid R@4 پر BM25 کو +10/−3، p = 0.09 سے beat کرتا ہے۔ یہ dense کو +10/−6، p = 0.45 سے beat کرتا ہے۔ اس corpus پر، 64 queries کے ساتھ، hybrid retrieval dense retrieval سے distinguishable نہیں۔ point estimates اور ہر recall column میں یہ بہتر ہے، اور evidence significance تک نہیں پہنچتا۔ internet پر تقریباً ہر hybrid-search blog post اوپر جیسی table report کرتی ہے اور کوئی interval نہیں؛ interval یہ کہتا ہے۔

Bi-encoder، cross-encoder، اور lift اصل میں کہاں ہے

اس حصے کا لنک: Bi-encoder، cross-encoder، اور lift اصل میں کہاں ہے

اب تک سب کچھ bi-encoder ہے: query model سے اکیلی گزرتی ہے، ہر chunk months ago اکیلا گزرا، اور دونوں dot product کے علاوہ کبھی نہیں ملتے۔ یہی index کو possible بناتا ہے — ایک بار embed کریں، ہمیشہ reuse کریں — اور یہی ceiling بھی ہے۔ model query اور chunk کو کبھی ساتھ نہیں دیکھتا۔

cross-encoder بالکل یہی کرتا ہے: pair کو ایک input کے طور پر لیتا ہے اور relevance score return کرتا ہے۔ کچھ بھی precompute نہیں ہو سکتا، اس لیے یہ index rank نہیں کر سکتا — مگر shortlist کو rerank کر سکتا ہے۔ ms-marco-MiniLM-L-6-v2 کے ساتھ hybrid top 25 کی reranking R@1 کو 0.094 (dense) سے 0.312 اور MRR کو 0.280 سے 0.447 پر لے جاتی ہے: اس chapter کی largest single improvement، اور واحد جو list کے top کو touch کرتی ہے نہ کہ tail کو۔

CPU پر اس کی cost 569 ms per query ہے، BM25 کے 1.14 ms اور vector scan کے 0.3 ms کے مقابل۔ Retrieval cost کا تقریباً دو ہزار گنا، پچیس documents کے لیے۔ یہی پورا bi-encoder/cross-encoder trade ایک number میں ہے، اور یہی وجہ ہے کہ architecture ہمیشہ ایک جیسی shape رکھتی ہے: wide recall والا cheap retriever، پھر ایسی shortlist پر expensive scorer جسے آپ afford کر سکتے ہیں۔ ColBERT دونوں کے بیچ بیٹھتا ہے، per-token vectors precompute کرتا ہے اور late interaction کرتا ہے جو cross-encoder سے cheaper اور dot product سے sharper ہے۔3

L2، cosine، اور وہ threshold جسے آپ نے earn نہیں کیا

اس حصے کا لنک: L2، cosine، اور وہ threshold جسے آپ نے earn نہیں کیا

Vector databases distances report کرتے ہیں، اور کون سا distance ہو یہ configuration option ہے۔ normalised vectors پر choice cosmetic ہے، اور identity کو ایک بار کرنا worth it ہے کیونکہ اس کے بعد سب کچھ vectors کے واقعی unit ہونے پر depend کرتا ہے۔ a=b=1\lVert a \rVert = \lVert b \rVert = 1 کے لیے:

ab2=a2+b22ab=22cosθ\lVert a - b \rVert^2 = \lVert a \rVert^2 + \lVert b \rVert^2 - 2\,a \cdot b = 2 - 2\cos\theta

تو cosine distance 1cosθ1 - \cos\theta exactly d2/2d^2/2 ہے۔ یہ Chapter 1 کا dot product اور norm، cashed ہے۔ اوپر والے index سے دو real chunk vectors پر checked، اور پھر 40,000 pairs پر:

TEXT
||a|| = 1.000000   ||b|| = 1.000000
L2 = 0.795183   L2^2/2 = 0.316158   1 - cos = 0.316158   diff = 7.66e-08
max |L2^2/2 - (1 - cos)| over 200 x 200 pairs = 8.3e-07

Floating-point noise تک exact — اور صرف اس لیے کہ vectors normalised ہیں۔ normalisation skip کریں تو identity false ہے، آپ کا threshold کچھ mean نہیں کرتا، اور document جو distance report کرتا ہے وہ اس پر depend کرتا ہے کہ اس کا text کتنا long تھا۔

اب وہ number جسے کوئی derive نہیں کرتا۔ retriever ہمیشہ کچھ نہ کچھ return کرتا ہے: یہ پورا index sort کرتا ہے اور list کا top آپ کو دے دیتا ہے، چاہے answer corpus میں کہیں ہو یا نہیں۔ threshold system کا واحد part ہے جو نہیں کہہ سکتا ہے — اور اسے set کرنے کے لیے آپ کو ایسی queries چاہئیں جنہیں کچھ بھی واپس نہیں ملنا چاہیے۔ یہ تیس ہیں: اکیس ایسی چیزوں کے بارے میں جو یہ corpus واقعی cover نہیں کرتا — streaming، rate limits، prompt caching، JSON schemas، agent loops، vector databases، prompt injection، image generation — اور نو paella، passports اور refund policies کے بارے میں۔ اسی index کے خلاف:

top-1 cosine distance
in-domain queries، تمام 64mean 0.445، range 0.270 – 0.721
in-domain، top-1 actually correctmean 0.370
in-domain، top-1 wrongmean 0.452
out-of-domain، تمام 30mean 0.699، range 0.497 – 0.867

Distributions separate ہوتی ہیں، اور overlap بھی کرتی ہیں۔ worst in-domain query اپنے answer سے (0.721) اس سے زیادہ دور ہے جتنا best out-of-domain query ایک irrelevant paragraph سے (0.497)، اس لیے کوئی threshold دونوں کو right نہیں کرتا۔ اسے real gate پر sweep کریں — زیادہ سے زیادہ چار chunks رکھیں، اور صرف وہ جو cut کے under ہوں:

thresholdin-domain answeredof which the answer was inout-of-domain answered
0.40017 / 6460 / 30
0.45038 / 64130 / 30
0.50050 / 64191 / 30
0.52552 / 64202 / 30
0.55055 / 64213 / 30
0.60060 / 64255 / 30
0.67562 / 642710 / 30
0.80064 / 642726 / 30
none64 / 642730 / 30

آخری column کو bluffs کے طور پر پڑھیں۔ threshold کے بغیر assistant backpropagation کے corpus سے “how do I renew my Spanish passport” کا confident، well-cited answer بناتا ہے، تیس میں سے تیس بار۔ 0.675 پر یہ تیس میں سے دس بار کرتا ہے۔ 0.525 پر یہ دو بار کرتا ہے، اور بارہ ایسے questions پر give up کرتا ہے جن کا جواب دے سکتا تھا۔

یہ trade ایک product decision ہے، اور اس کا right end اس پر depend کرتا ہے کہ wrong answer آپ کو کتنی cost کرتا ہے۔ جو negotiable نہیں وہ آخری column کا موجود ہونا ہے۔ اگر آپ نے کبھی اپنے retriever کو ایسی questions کے خلاف measure نہیں کیا جن سے اسے refuse کرنا چاہیے، تو آپ کے پاس threshold نہیں — ایک number ہے۔

0.675 پر دس bluffs میں سے دو دکھاتے ہیں کہ یہ دو ways سے کیسے fail ہوتا ہے۔

the two shapes of a confident wrong retrievalTEXT
query: "how much does prompt caching save on a long conversation"
  [1] d=0.497  13-inference-optimization > Prefill and decode are two different machines
  [2] d=0.532  13-inference-optimization > The cache is also the bill

query: "what is the capital of france"
  [1] d=0.671  12-reasoning > The model does not think. It computes for longer.
      "…it is why 'think step by step' does nothing for what is the capital of France."

پہلا near miss ہے: corpus KV cache کو detail میں explain کرتا ہے، query prompt cache کے بارے میں ہے، words وہی words ہیں، اور 0.497 پورے experiment میں زیادہ تر correct in-domain retrievals سے closer ہے۔ embedding نہیں جانتی کہ ایک ہی name والی دو caches different machines ہیں۔ دوسرا literal match with no answer ہے: corpus exact phrase “what is the capital of France” contain کرتا ہے، ایک ایسی question کی example کے طور پر جسے reasoning کی ضرورت نہیں۔ retriever right ہے؛ answer وہاں نہیں ہے۔ کوئی بھی system جو “I found something similar” کو “I found the answer” سمجھتا ہے اس evidence پر Paris assert کرے گا — یا، worse، نہیں کرے گا۔

model کے پاس facts کے لیے کوئی separate faculty نہیں۔ true sentence produce کرنا اور plausible sentence produce کرنا same operation ہے — Chapter 8 کی next-token prediction — اور اس operation میں کچھ بھی mark نہیں کرتا کہ کون سی کون ہے۔ 2025 analysis جس نے اسے reframe کیا، argue کرتی ہے کہ training اور evaluation pipeline actively guessing کو reward کرتی ہے: benchmarks binary accuracy سے score کرتے ہیں اور abstention کا کوئی credit نہیں دیتے، اس لیے ایسا model جو ہمیشہ answer کرتا ہے ایک identical model سے ہمیشہ زیادہ score کرتا ہے جو “I don't know” کہتا ہے جب اسے نہیں معلوم، اور post-training اسی کے مطابق optimise کرتی ہے۔6 اس reading پر hallucination کوئی mysterious defect نہیں۔ یہ وہ ہے جو آپ کو تب ملتا ہے جب آپ wrong answer کی penalty کے بغیر multiple-choice exam grade کرتے ہیں۔

اس کی shape دیکھیں۔ contrastive sentence embeddings پر identifiers کے ساتھ آٹھ papers مانگے گئے تو Qwen2.5-0.5B-Instruct نے perfect format میں آٹھ lines produce کیں۔ تمام آٹھ identifiers well-formed ہیں۔ تمام آٹھ arXiv پر real papers پر resolve ہوتے ہیں۔ آٹھ میں سے zero claimed paper ہیں۔

8 references, checked one by one against the arXiv APITEXT
claimed  arXiv:1907.06432 - Contrastive Sentence Embeddings for Text Retrieval
actual   A Neural Turing~Machine for Conditional Transition Graph Modeling

claimed  arXiv:1809.08669 - Contrastive Learning of Sentence Representations…
actual   Collapsing Superstring Conjecture

claimed  arXiv:1807.08669 - Contrastive Learning of Sentence Representations…
actual   Automatic Speech Recognition for Humanitarian Applications in Somali

یہ small model ہے اور rate اس کا اپنا ہے؛ frontier model کہیں کم invent کرتا ہے۔ mechanism generalise ہوتا ہے، اور یہی اگلے rule کی وجہ ہے۔ “does this identifier exist” check کرنے والا validator تمام آٹھ pass کر دیتا ہے، اور user جو ایک پر click کرتا ہے real archive کے real page پر land کرتا ہے جہاں mapping invented ہونے کا پتہ لگانے کا کوئی طریقہ نہیں۔ failure identifier یا format میں نہیں۔ یہ association میں ہے — ٹھیک وہ چیز جو language model plausibility سے produce کرتا ہے۔

تو: model [1] اور [2] لکھتا ہے، اور link کبھی نہیں لکھتا۔ numbers server کے retrieved fragments کو refer کرتے ہیں، اور server — جو exactly جانتا ہے کہ ہر number کس document اور کن offsets سے آیا — بعد میں document، label اور URL attach کرتا ہے۔ model کے invent کرنے کے لیے کچھ نہیں کیونکہ اسے کبھی وہ ایک چیز مانگی ہی نہیں جاتی جسے وہ invent کرے گا۔

prompt.tsTS
export function buildContext(question: string, hits: Scored[]) {
  const citations: Citation[] = hits.map((h, i) => ({
    index: i + 1,
    documentId: h.chunk.documentId,
    documentName: h.chunk.documentName,
    locatorLabel: label(h.chunk),
    fragment: `#char=${h.chunk.locator.flow.from},${h.chunk.locator.flow.to}`,  
    quote: h.chunk.content,          // the OWN content, never `text`
    cosineDistance: h.cosineDistance,
  }));
  const blocks = citations
    .map((c) => `[${c.index}] ${c.documentName} - ${c.locatorLabel}\n${c.quote}`)
    .join("\n\n");
  const prompt =
    `Answer using ONLY the numbered sources below. Cite every claim as [n].\n` +
    `If the sources do not contain the answer, say so and stop.\n\n` +
    `SOURCES\n${blocks}\n\nQUESTION\n${question}`;
  return { prompt, citations };
}

Opening question پر اسے run کریں تو چار chunks 591-token prompt اور ایک table بن جاتے ہیں جسے model کبھی نہیں دیکھتا:

TEXT
[1] 04-classification  How many test examples do I need?      #char=28215,28701  d=0.594
[2] 04-classification  Three splits, and the leak…            #char=20329,20839  d=0.598
[3] 04-classification  How many test examples do I need?      #char=25873,26272  d=0.600
[4] 04-classification  How many test examples do I need?      #char=25554,25871  d=0.605

Locator وہ part ہے جسے لوگ skip کرتے ہیں اور پھر later add نہیں کر پاتے۔ #char=25873,26272 document کے canonical text میں ایک range ہے؛ PDF کے لیے equivalent #page=12 ہے، audio یا video کے لیے #t=132.4,158.9، spreadsheet کے لیے sheet اور A1 range۔ یہ دونوں inventions نہیں — #page= PDF Open Parameters ہے اور #t= W3C Media Fragments، جنہیں browsers video اور audio elements پر natively honour کرتے ہیں۔ locator کے بغیر citation document name ہے، اور document name citation نہیں؛ یہ suggestion ہے کہ user جا کر دیکھے۔

اور جب threshold سے کچھ pass نہیں ہوتا، pipeline model تک پہنچتی ہی نہیں:

TEXT
NO ANSWER: nothing under cosine distance 0.675 for "what is the offside rule in football"
NO ANSWER: nothing under cosine distance 0.675 for "how do i renew my spanish passport"
NO ANSWER: nothing under cosine distance 0.675 for "how do i build an agent loop with tools"

یہ system prompt کی کسی بھی instruction سے cheaper اور زیادہ reliable refusal ہے، کیونکہ یہ probabilistic system سے request کے بجائے دو numbers کے درمیان comparison ہے۔

Retriever کو generator سے الگ evaluate کریں

اس حصے کا لنک: Retriever کو generator سے الگ evaluate کریں

اس chapter میں ہر measurement retriever کو score کرتی ہے اور model سے ایک بار بھی answer لکھنے کو نہیں کہتی۔ یہ deliberate ہے، اور یہی وہ piece ہے جسے اکثر teams skip کرتی ہیں۔

RAG system کے دو failure modes ہیں جو باہر سے identical نظر آتے ہیں۔ retriever نے passage نہیں find کیا؛ یا اس نے find کیا اور generator نے اسے ignore کیا، contradict کیا، یا اسے کسی ایسی چیز کے ساتھ blend کیا جس پر وہ پہلے سے believe کرتا تھا۔ صرف final answer کو score کریں تو دونوں indistinguishable ہیں، اس لیے آپ prompts کو ایسے problem کے خلاف tune کرتے ہیں جو آپ کے chunker میں رہتا ہے۔ Recall@k، MRR اور answer-destroyed count کو generation call کی ضرورت نہیں، وہ ہر deploy پر run کرنے کے لیے کافی cheap ہیں، اور وہ Chapter 15 کا harness ہیں ایک different scoring function کے ساتھ — same request، deadline، concurrency اور tally، live conversation کے بجائے fixed question set پر۔

انہیں intervals کے ساتھ report کریں۔ Chapter 4 کی arithmetic unchanged apply ہوتی ہے: 64 queries پر 0.5 recall تقریباً ±0.12 کا 95 % Wilson interval رکھتا ہے، اس لیے کوئی strategy دوسری سے four points ahead ہو تو اس نے آپ کو کچھ نہیں بتایا۔ paired test استعمال کریں جب دونوں strategies same questions کا answer دیتی ہیں، جو یہاں ہمیشہ کرتی ہیں — اسی نے “E looks better than A” کو p = 0.0015 بنایا۔

اور آخری honesty: RAG hallucination کو reduce کرتا ہے، remove نہیں کرتا۔ right passage کو prompt میں ڈالنا model کو اسے use کرنے پر oblige نہیں کرتا، اور literature نے original paper سے یہی کہا ہے۔7 Production میں دو چیزیں اسے worse کرتی ہیں۔ Long contexts degrade ہوتے ہیں — model long prompt کے start اور end پر information کو middle کے مقابل زیادہ reliably find کرتا ہے، اس لیے twenty chunks instead of four accuracy lower کر سکتے ہیں while bill raise کرتے ہیں، ایک effect جو Chapter 24 میں measured ہے۔ اور retrieval right ہو کر بھی insufficient ہو سکتی ہے، جیسا کہ اوپر دو caches نے دکھایا۔ SelfCheckGPT وہ claims flag کرتا ہے جو resampling survive نہیں کرتے؛8 Self-RAG model کو اپنے retrieve-and-critique tokens emit کرنا train کرتا ہے؛9 TruthfulQA نے failure mode کو پہلے place میں legible بنایا۔10 کوئی بھی gap close نہیں کرتا، اور ایسا system جو retrieved text کو proof کے طور پر present کرتا ہے اس نے sourced کو true سمجھ لیا ہے۔

System کا وہ half جو کسی query سے پہلے چلتا ہے

اس حصے کا لنک: System کا وہ half جو کسی query سے پہلے چلتا ہے

retriever ایک pipeline کا visible part ہے جس کی failures سب پہلے، اندھیرے میں ہوتی ہیں۔ ان میں تین recur کرتی ہیں۔

Extraction وہ جگہ ہے جہاں content مرتا ہے۔ PDF text نہیں؛ یہ drawing instructions ہے۔ Two-column layouts interleave ہوتے ہیں، tables word soup بن جاتے ہیں، page headers ہر chunk میں repeat ہوتے ہیں، اور scanned page میں text بالکل نہیں ہوتا جب تک OCR اسے کچھ نہ دے، confidence کے ساتھ۔ اوپر measured ہر چیز نے assume کیا کہ extractor نے اپنا کام کیا؛ production میں اکثر نہیں کرتا، اور symptom تین layers دور bad retrieval کے طور پر appear ہوتا ہے۔

Index پر اسے بنانے والے model کی مہر ہوتی ہے۔ دو models کی embeddings comparable نہیں — نہ “less accurate”، comparable ہی نہیں، کیونکہ وہ different spaces میں points ہیں۔ embedding model بدلیں تو store میں ہر vector garbage ہے جب تک اسے rebuild نہ کیا جائے۔ اس لیے model name، dimension count، pipeline version اور extractor version index time پر ہر document کے ساتھ written ہوتے ہیں۔ ان کے بغیر، upgrade day پر آپ نہیں بتا سکتے کون سے documents stale ہیں اور کون سے current، اور half-migrated index کہیں بھی error کے بغیر confident nonsense return کرتا ہے۔

ایک broken document folder کو break نہیں کرنا چاہیے، اور counters کو وہ count کرنا چاہیے جو ہوا۔ جو document extraction میں fail ہو وہ اپنی reason کے ساتھ failed state میں end ہوتا ہے، visible اور retryable، جبکہ باقی ننانوے searchable رہتے ہیں؛ اور indexed chunks کی تعداد server لکھتا ہے جب finish کرتا ہے، client upload کے وقت declare نہیں کرتا۔ ایسا folder جو 400 fragments report کرے اور 40 رکھتا ہو ایک جھوٹ ہے جو صرف unanswerable question کے طور پر surface ہوتا ہے۔

اس chapter کا system ایسے questions کے answer دیتا ہے جن کے answers لکھے ہوئے ہیں۔ یہ انہیں retrieve کرتا ہے، rank کرتا ہے، جب نہیں کر سکتا تو refuse کرتا ہے، اور cite کرتا ہے کہ کہاں دیکھا۔ اپنے documents پر assistant سے اکثر لوگ یہی چاہتے ہیں، اور یہ ایک specific way میں bounded ہے: retrieval صرف وہی return کر سکتی ہے جو کسی نے لکھا ہو۔

اب دوسرا half رہ جاتا ہے۔ جو کچھ آپ model سے کروانا چاہتے ہیں اس میں سے کچھ document میں fact بالکل نہیں — ایک format جسے اسے hold کرنا ہے، tone، چار hundred labels والی taxonomy، decide کرنے کا ایک طریقہ جو دس ہزار past examples میں رہتا ہے اور کہیں کسی paragraph میں نہیں۔ Retrieval یہ deliver نہیں کر سکتی، کیونکہ retrieve کرنے کے لیے کچھ نہیں؛ longer prompt صرف Chapter 16 کا bill skill کے بجائے skill کی description کے لیے pay کرتا ہے۔

باب 20 یہی decision ہے — fine-tune، retrieve یا prompt — اور اس کی finding یہ ہے کہ decision technical ہونے سے پہلے economic ہے: تینوں کو same question پر end to end price کیا جاتا ہے، اور crossover ایک token count ہے۔ جو question اسے open کرتا ہے وہ ہے جس کا یہ chapter answer نہیں دے سکتا۔ یہ نہیں کہ answer کہاں لکھا ہے، بلکہ جب وہ کبھی لکھا ہی نہ گیا ہو تو آپ کیا کرتے ہیں۔


اس chapter میں measured ہر چیز نے ایک corpus اور ایک instrument استعمال کیا، اور دونوں reproducible ہیں۔ corpus اس course کے chapters 1 تا 13 ہیں جیسے وہ 7 September 2026 کو تھے — 13 documents، 359,067 characters، 127 sections، front matter اور bibliographies removed۔ وہ chapters edit ہوتے رہتے ہیں، اس لیے آج same rule apply کرنے سے چند ہزار characters زیادہ count ہوتے ہیں: section count unchanged ہے اور نیچے ہر conclusion بھی، مگر character total ایک snapshot ہے اور اسے اسی طرح label کیا گیا ہے۔ ground truth 32 questions ہے، ہر ایک کے ساتھ verbatim sentence جو corpus میں exactly once occur ہوتی ہے اور کبھی section heading نہیں، 64 queries کے لیے دو phrasings میں پوچھی گئی۔ Retrieval embeddings sentence-transformers/all-MiniLM-L6-v2 ہیں (384 dimensions، mean-pooled، L2-normalised، 256-token window)؛ reranking top 25 پر cross-encoder/ms-marco-MiniLM-L-6-v2 ہے؛ generation example greedy decoding کے ساتھ Qwen/Qwen2.5-0.5B-Instruct ہے۔ تمام timings single-threaded CPU ہیں۔ اس chapter کو produce کرنے کے لیے کوئی paid API call نہیں کی گئی، اسی لیے یہاں ہر latency local ہے اور اسی طور label ہے۔

TypeScript میں دکھایا گیا chunker وہی chunker ہے جو measured تھا: same rule implement کرنے والے Python instrument اور ts/chunk.ts کو پورے corpus پر chunk for chunk compare کیا گیا اور تمام 940 chunks، texts اور offsets alike پر agree کرتے ہیں۔ Intervals 95 % پر Wilson ہیں؛ paired comparisons discordant pairs پر two-sided exact sign tests ہیں۔

اوپر cite کیے گئے تمام fourteen identifiers کو arXiv API کے against resolve کیا گیا اور 7 September 2026 کو title by title check کیا گیا — جو، ان آٹھ کو دیکھتے ہوئے جو نہیں تھے، اس particular chapter کے لیے کم از کم یہی کرنا بنتا تھا۔

  1. Robertson, S. and Zaragoza, H. The Probabilistic Relevance Framework: BM25 and Beyond. Foundations and Trends in Information Retrieval 3(4), pp. 333–389 (2009). saturation function اور اوپر استعمال ہونے والے دو constants کا source، اور یہ پڑھنے کی جگہ کہ bb exists at all کیوں ہے۔

  2. Cormack, G. V., Clarke, C. L. A. and Büttcher, S. Reciprocal Rank Fusion Outperforms Condorcet and Individual Rank Learning Methods. SIGIR 2009. k=60k = 60 ان کا ہے، اور method کا point یہ ہے کہ اسے fused score scales کے درمیان calibration کی ضرورت نہیں۔

  3. Khattab, O. and Zaharia, M. ColBERT: Efficient and Effective Passage Search via Contextualized Late Interaction over BERT. arXiv:2004.12832 (2020). dot product اور cross-encoder کے درمیان middle ground۔ Reimers, N. and Gurevych, I., Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks, arXiv:1908.10084 (2019)، وہ bi-encoder ہے جس پر اس chapter کا index built ہے اور Chapter 8 میں measured تھا۔

  4. Malkov, Yu. A. and Yashunin, D. A. Efficient and Robust Approximate Nearest Neighbor Search using Hierarchical Navigable Small World Graphs. arXiv:1603.09320 (2016). graph index جو currently sold اکثر vector databases کے پیچھے ہے۔

  5. Johnson, J., Douze, M. and Jégou, H. Billion-scale Similarity Search with GPUs. arXiv:1702.08734 (2017). FAISS، اور اوپر box میں measured IVF کا reference implementation۔

  6. Kalai, A. T., Nachum, O., Vempala, S. S. and Zhang, E. Why Language Models Hallucinate. arXiv:2509.04664 (2025). یہ argument کہ hallucination binary-accuracy grading سے produce ہوتی ہے جو abstention کو کبھی reward نہیں کرتی، اور اس لیے modelling problem ہونے سے پہلے evaluation problem ہے۔

  7. Lewis, P., Perez, E., Piktus, A., Petroni, F., Karpukhin, V., Goyal, N., Küttler, H., Lewis, M., Yih, W., Rocktäschel, T., Riedel, S. and Kiela, D. Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks. arXiv:2005.11401 (2020). وہ paper جس نے pattern کو name دیا اور یہ پڑھنے کی جگہ کہ یہ کیا fix کرتا ہے اور کیا نہیں۔ Guu et al., REALM: Retrieval-Augmented Language Model Pre-Training, arXiv:2002.08909 (2020)، contemporaneous work ہے جو retriever کو model کے ساتھ jointly train کرتا ہے بجائے اس کے کہ اسے bolt on کرے؛ Karpukhin et al., Dense Passage Retrieval for Open-Domain Question Answering, arXiv:2004.04906 (2020)، وہ جگہ ہے جہاں اس chapter بھر استعمال ہونے والا two-encoder dense retriever آتا ہے؛ اور Izacard and Grave, Leveraging Passage Retrieval with Generative Models for Open Domain Question Answering, arXiv:2007.01282 (2020)، many passages کو one generator کو feed کرنے کے لیے fusion-in-decoder arrangement ہے۔ Gao et al., Retrieval-Augmented Generation for Large Language Models: A Survey, arXiv:2312.10997 (2023)، بعد میں آنے والی ہر چیز کا map ہے، including HyDE (Gao et al., Precise Zero-Shot Dense Retrieval without Relevance Labels, arXiv:2212.10496, 2022)، جو question کے بجائے hypothetical answer کو embed کرتا ہے۔

  8. Manakul, P., Liusie, A. and Gales, M. J. F. SelfCheckGPT: Zero-Resource Black-Box Hallucination Detection for Generative Large Language Models. arXiv:2303.08896 (2023). resampling سے detection، model کے internals تک access کے بغیر اور external knowledge base کے بغیر۔

  9. Asai, A., Wu, Z., Wang, Y., Sil, A. and Hajishirzi, H. Self-RAG: Learning to Retrieve, Generate, and Critique through Self-Reflection. arXiv:2310.11511 (2023). model کو ہر turn پر retrieve کرنے کے بجائے یہ decide کرنا train کرنا کہ retrieve کب کرنا ہے۔

  10. Lin, S., Hilton, J. and Evans, O. TruthfulQA: Measuring How Models Mimic Human Falsehoods. arXiv:2109.07958 (2021). ایسا benchmark جو ان questions سے بنا جہاں plausible answer اور true answer different ہوتے ہیں، جو ایک sentence میں پوری difficulty ہے۔


تیار کردہ

David Vicente Campos

NeuraLIA Labs کے بانی اور MyRealFood کے شریک بانی

میں یونیورسٹی آف لیون سے کمپیوٹر انجینئر ہوں۔ میں نے MyRealFood کی مشترکہ بنیاد رکھی، جہاں بطور CTO میں نے وہ ایپ بنائی جسے لاکھوں لوگ بہتر غذا کے لیے استعمال کر چکے ہیں، اور میں نے NeuraLIA Labs قائم کیا، جہاں میں AI مصنوعات بناتا ہوں۔ یہاں میں ان باتوں کے بارے میں لکھتا ہوں جو اس سفر میں مجھے سمجھنی پڑیں، اس طرح جس طرح کاش کسی نے مجھے سمجھائی ہوتیں۔

مصنف کے بارے میں مزید

NeuraLIA Labs کی جانب سے شائع کردہ۔

نئی پوسٹس اپنے ان باکس میں پائیں

AI کی خبریں، گائیڈز اور پروڈکٹ اپ ڈیٹس — جب ہم آپ کے وقت کے قابل کچھ شائع کریں تو ایک مختصر ای میل۔

کورس انڈیکس

Abstract software decision engine with branching paths, probability nodes, and glowing gates.
jev14 منٹ مطالعہ

Jev AI ماڈل فیصلوں کے لیے بنایا گیا ہے، نثر کے لیے نہیں

TypeSafe AI کا Jev اس لیے توجہ کھینچ رہا ہے کہ یہ software intelligence کو احتمال کے مسئلے کے طور پر دیکھتا ہے: درست branch چنیں، confidence منسلک کریں، اور جب code کو فیصلہ چاہیے ہو تو text لکھوانے کے لیے LLM کو ادائیگی سے بچیں۔

Abstract agent runtime sorting documents, memory blocks and pointer nodes inside a bounded context frame.
context-engineering14 منٹ مطالعہ

طویل مدتی AI ایجنٹس کے لیے کانٹیکسٹ انجینئرنگ

طویل عرصے تک چلنے والے ایجنٹس صرف اس لیے ناکام نہیں ہوتے کہ ونڈو چھوٹی ہے۔ وہ اس وقت ناکام ہوتے ہیں جب فائلیں، ٹول آؤٹ پٹس اور پرانی ہسٹری اس کام کو باہر دھکیل دیتی ہیں جسے ایجنٹ نے مکمل کرنا تھا۔

ماڈل چننے کا کام LIA کے سپرد کرنے کے لیے تیار ہیں؟

ہر AI ماڈل ایک ہی جگہ — آج ہی مفت شروع کریں۔