Галоўная / Артыкулы

Дзесяць спосабоў скасаваць галюцынаціі без дакладнай наладкі

Дзесяць наладакаў на рэвэле сістэмы, якія зменшаюць галюцінаціі LLM у агенце для е-камерцыі: лепшы кантэкст, адзыскванне даных, графы, інструменты, параболка і ацэнка, без падтрымкі.

Выдавец: REACTAPP.TOP9 хв чытання2156 слоў

Крыніцы: 10 Ways to Reduce AI Hallucinations Without Fine-Tuning Your Model

Калі асістэнт кажа кліенту "Ваша вярненне сумы ўжо обрабоўвана", а вярненне сумы не існуе, прычыной зазвычай не ёсць сама модэль. Сістэма, якая яе апрацоўвае, залішыла прасечку, і модэль заполніла гэтую прасечку на адгадванні. Статус замовлення быў відсутны, запыт вярнуў некарэктныя даны, кантэкст быў занадта заплутаны, вызовы інструментаў не перакантроліваліся, а пярэйшыя успехі былі забуты.

Можна значна зменшыць галюцынаціі, не чынячы нічога з параметрамі модэлі. Прыклад, які тут паказаны, — гэта асістэнт у сферэ е-камерцыі, які перакантролюе замовленні, выдае вярненні сумы і апошніяе інформацыю пра доставку, і мы будзем ударожваліць яго поштоўку за раз ад слоя.

Простая версія

Кліент пытаецца: "Дзе мае замовленне №48291?" Першыя версіі прылада проста перадаюць гэты запыт далей:

const response = await client.responses.create({
  model: "gpt-5",
  input: `
    Where is order #48291?
  `
});

console.log(response.output_text);

Мадэль можа адказаць: «Ваша замовка выдана на доставку і прыбудзе сёньдзе». Чудаза, толькі ёй не вядома, дзе знаходзіцца замовка 48291. Яна стварыла правдападобную фразу на адважыце патэранаў з своіх дадзеных для навучэння. Гэта галюцынацыя.

Тое, чаго вы хачаце, выглядае больш-цяга так:

Customer
   ↓
AI Agent
   ↓
Order System
   ↓
Actual Order State
   ↓
AI Agent
   ↓
Response

Модэль должна адаптавацца да рэальнасці, а не выдумваць яе.

1. Аддаюце тыя даны, якія ўжо ў вас ёсць

Першая правіла: не заставляйце модэль здагадвацца пра тое, што знае ваш бэкенд. Зазначыце, што бэкенд зберагае гэты запіс:

{
  "orderId": "48291",
  "status": "SHIPPED",
  "carrier": "FedEx",
  "trackingNumber": "784512963",
  "estimatedDelivery": "2026-08-25"
}

Практыкуйце яго разам з пытаннем:

const context = {
  order: {
    id: "48291",
    status: "SHIPPED",
    carrier: "FedEx",
    trackingNumber: "784512963",
    estimatedDelivery: "2026-08-25"
  }
};

const response = await client.responses.create({
  model: "gpt-5",
  input: `
    Answer the customer using only the supplied order information.
    Context:
    ${JSON.stringify(context, null, 2)}
    Customer:
    Where is my order #48291?
  `
});

Цяе модэль больш не патрабуецца ведаць пра статус замовлення. Яе задача скарочваецца да таго, каб поясніць кліянту вядомы факт, што ўзніклае набагато безпечней. Пораўняйце гэтыя два падходы:

Bad:

Customer → LLM → Answer

Better:
Customer
   ↓
Retrieve state
   ↓
Build context
   ↓
LLM
   ↓
Answer

Гэта ўсё сутнасць інжыніерыі кантэксту.

2. Спачатку запрашайце, пасля — ствараце

Іншы кліент запытаеся пра правіла вярнення апаратуры, купленай пад святковым распродажам. Гэтая адказ не знаходзіцца ў модэлі; яна знаходзіцца ў вашай базе дадзэнняў правіл, дакументах продуктаў, правілах акцый і рэгіональных умовах. Таму запрашайце яе першым крокам, прычым ствараць адказ. Базовы алгорытм RAG:

Customer Question
       ↓
    Retrieve
       ↓
     Rank
       ↓
Build Context
       ↓
      LLM
       ↓
    Answer

І простая рэалізацыя:

const results = await vectorStore.search({
  query: customerQuestion,
  topK: 10
});

const relevant = results
  .filter(item => item.score > 0.8)
  .slice(0, 5);
const context = relevant
  .map(item => item.content)
  .join("\n\n");
const answer = await generateAnswer(
  customerQuestion,
  context
);

У гэтым случае якосьць важлівейша за колькасць. Падача модэлю 30 дакументаў не робіць яе розумней. Калі трохі дакументаў маюць значэнне, то рэшта 27 — толькі шум.

3. Адмахніцеся ад непатрэбнаў

Уявіце сабе, калі асістэнт прыме гэты стос:

20 retrieved documents
+
15 previous messages
+
10 previous tool responses
+
customer profile
+
product catalog
+
order history
+
promotion metadata

Цякмо, кліент спытаецца толькі: «Магчыма, мне можна вернуць гэтыя наушнікі?» Шаблон не патрэбныя пяцьнаццаць пакананняў, некалякія замовленні, іншыя лініі продуктав, заканчыліся акцыі чыста старыя правілы даставкі. Лепшы механізм фільтруе раней, чым выдае запыт:

Available Information
        ↓
Relevance Filtering
        ↓
Metadata Filtering
        ↓
Ranking
        ↓
Deduplication
        ↓
Context Compression
        ↓
LLM

У кодзе ў выглядзе:

const context = results
  .filter(x => x.score >= 0.82)
  .filter(x => x.metadata.category === "returns")
  .filter(x => x.metadata.region === customer.region)
  .sort((a, b) => b.score - a.score)
  .slice(0, 5)
  .map(x => x.content);

Вы не прагнуце максымізаваць кантэнт токэнаў. Вы прагнуце падняць спяваработку сігналу і шуму. Хорашыя правілы: дайце модэлю все, што яму трэба, і нічога, што яму не трэба.

4. Іспользуйце граф знанняў для структураваных фактов

RAG падходзіць для дакументаў. Багатыя запытанні ў сферэ е-камерцыі зовсім не стосуюцца дакументаў. Яны стосуюцца асоціяцый: які склад выпалняе гэты замовленне, якая оплата яго падтрымала, якія тавары ўключаныя ў акцыю, якія замовленні будуць парадуцаны, якшо склад перастане працаваць. Гэта проблемы графа. Спрасаваны граф:

Customer
   │
   └── PLACED → Order
                  │
                  ├── CONTAINS → Product
                  │
                  ├── PAID_BY → Payment
                  │
                  ├── FULFILLED_BY → Warehouse
                  │
                  └── SHIPPED_BY → Carrier

Калі корыстнік спытаецца, які склад апрацоўвае яго замовленне, сістэма можа перайсці па гэтым шляху:

Order #48291
      ↓
FULFILLED_BY
      ↓
Warehouse #17

з выкалкай графа на кшталт:

MATCH (o:Order {id: "48291"})
      -[:FULFILLED_BY]->
      (w:Warehouse)
RETURN w.id, w.name, w.location;

Рэзультат стае надзеяным кантэкстам:

{
  "orderId": "48291",
  "warehouse": {
    "id": "WH-17",
    "name": "Delhi Fulfillment Center",
    "location": "Delhi"
  }
}

Размясціце два падчынні паляўкамі. Без структуры:

Without structured knowledge:

User → LLM
         ↓
      Guess

І з графам у цыкле:

With Knowledge Graph:

User
 ↓
Entity Identification
 ↓
Graph Traversal
 ↓
Verified Relationship
 ↓
Context
 ↓
LLM

Гэта ўсё больш практычна, калі асістэнт павінен вырашвац задачы, выкарыстоўваючы кальколька разных сістэм.

5. Запытайце пра доказы

Не проста запытайце аб адказе. Запытайце аб адказе плюс прычыны, якія яго падтрымляюць. Структураваны адказ можа выглядаць так:

{
  "answer": "Your order is being fulfilled by Warehouse WH-17.",
  "confidence": 0.98,
  "evidence": [
    {
      "type": "order_record",
      "source": "orders_db",
      "orderId": "48291"
    },
    {
      "type": "warehouse_relationship",
      "source": "knowledge_graph",
      "warehouseId": "WH-17"
    }
  ]
}

Вы можэце стварыць прычыну для выканання гэтага прыкметы за дапамою інструкцый:

For every factual claim:
1. Identify supporting evidence.
2. Use only available evidence.
3. Never invent a source.
4. If evidence is unavailable, say so.
5. Clearly distinguish facts from inference.

Тады прыкладнэнне можа дзеяць на адпаведнасць:

if (result.confidence < 0.7) {
  return escalateToHuman(result);
}

Гэта змініў просты прайскурс:

LLM → Answer

С перапрацоўкамі на паўзе:

LLM
 ↓
Answer
 ↓
Evidence
 ↓
Confidence
 ↓
Decision

6. Даюце агенту інструменты замест таго, каб ён сам дагадваўся

Інодзе найлепшая мера прыменэ не ў тым, каб LLM ужо ўсё-такі адпавядаў. Калі кліент спытае, чыі здарыўся вярненне грошаў, пакажыце можлівасць пашуку:

const tools = [{
  name: "get_refund_status",
  description: "Retrieve the current refund status for an order",
  parameters: {
    type: "object",
    properties: {
      orderId: {
        type: "string"
      }
    },
    required: ["orderId"]
  }
}];

Экзекуцыя адбываецца так:

Customer
   ↓
LLM
   ↓
get_refund_status()
   ↓
Payment System
   ↓
Actual Refund State
   ↓
LLM
   ↓
Customer

У зямест на неканчатковае заявленне „Ваша вярненне грошаў мае прыйсці за 5–7 дзён“, агент можа сказаць, што процэс вярнення пачаўся ўчора і яшчэ чакае на завершэнне, калі толькі гэта правда. Калі ёсць можласць отрымаць адпаведзь у рэальным свеце, запытайце пра гэта там.

7. Перакананне правільнасці вхідных і выхідных даных інструмента

Толькі вызов інструмента не робіць агента надзеяным. Мадэль все ўсё можа стварыць некарэктны запіт. Кліент прасіць вярнуць 100 долераў з замовлення 48291, а мадэль выдае:

{
  "orderId": "48291",
  "amount": "one hundred",
  "currency": "dollars"
}

Але ваш API для платэжа выкарыстоўвае:

{
  "orderId": "48291",
  "amount": 100,
  "currency": "USD"
}

Дадзіце параболік пераканання схемы, напрыклад, з Zod:

import { z } from "zod";

const RefundRequest = z.object({
  orderId: z.string(),
  amount: z.number().positive(),
  currency: z.enum(["USD", "EUR", "GBP", "INR"])
});
const refundRequest = RefundRequest.parse(
  modelOutput
);

Не зупыняйцеся толькі на тыпах. Пераканаўцеся таксама з правіламі бізнесу:

if (refundRequest.amount > order.total) {
  throw new Error(
    "Refund amount exceeds order total"
  );
}

Тады лінія практык становіцца такой:

LLM
 ↓
Schema Validation
 ↓
Business Validation
 ↓
Permission Check
 ↓
Execute
 ↓
Response Validation
 ↓
Accept / Retry / Escalate

Гэта мае вялікое значэнне для агентаў, якія выконваюць рэальныя дзеянні. LLM ніколі не павінен маты кантроль над дадзеннямі, якія выконваюцца.

8. Раздзеляйце факты ад логічных вывадоў

Тонкі, але эфектыўны спосаб — храніць тое, што знае сістэма, окрэмна ад таго, да чаго дайшоў мадэль:

{
  "facts": [
    "Order 48291 is shipped",
    "Order 48291 is fulfilled by Warehouse WH-17",
    "Warehouse WH-17 is currently operating"
  ],
"reasoning": [
    "The order is likely to remain on schedule"
  ],
  "conclusion": "The order is currently expected to arrive on time."
}

Яны несу разную паверыненасць. Першыя заявы выйшлі з сістэм, а последнія — гэта вывад. Калі фінальны адказ выявляецца некорэктным, можна задаць аднай простай запытанню:

Was the fact wrong?

OR
Was the reasoning wrong?

Гэта значная проста для дыягностыкі. Вы нават можэце паказаць внутршніе нараджэнні розбівкі:

FACT
→ Order shipped

FACT
→ Estimated delivery: Aug 25
INFERENCE
→ Delivery is currently expected on schedule

Невялкая разліка дапамагае забезпечыць высокі рэгістрацыйны статус.

9. Учыцца на рэзультатах выканання, а не на трэнінгу

Давайце змусім агента падбягаць да павышэння качэння без додатковага налаштавання. Кліент прасіць анулювацыю замовлення 48291. Агент пераканалівае замовленне:

{
  "orderId": "48291",
  "status": "PROCESSING",
  "cancelable": true
}

Потым выклікаецца:

cancel_order(48291)

і адказвае:

{
  "success": true,
  "cancellationId": "CAN-83921"
}

Такі рэзультаты варта зберагчы. Зберажыце успешны запуск:

{
  "task": "Cancel order",
  "orderState": "PROCESSING",
  "action": "cancel_order",
  "result": "SUCCESS",
  "cancellationId": "CAN-83921"
}

Калі пазней з’явіцца падобны запіт, спачатку шукайце адпаведныя практычныя успехі раней:

New Request
    ↓
Find Similar Successful Execution
    ↓
Retrieve Relevant Pattern
    ↓
Check Current Order State
    ↓
Generate Action
    ↓
Validate
    ↓
Execute

Нявяскі таксама научаюць. Празьба, якая не выйшла, залечыць след:

Attempt 1
    ↓
cancel_order()
    ↓
Rejected: Order already shipped
    ↓
Agent retrieves shipping information
    ↓
Explains cancellation is unavailable

Эія следы стаюць ведамасцю, а цыкл зворачнай связі выглядае так:

Execute
   ↓
Observe
   ↓
Evaluate
   ↓
Store Experience
   ↓
Improve Future Context

Гэта можна назваць навчаннем пад час выканання. Не трэба парадзейвання.

10. Ацэніце кожную змяну

На завершанне пераканайцеся, чы не дапомагала якась змяна. Спадзяймо, што вы змянілі падход да пошуку. Фраза «Адказы сталі крашчымі» — гэта не доказ. Створыце набор для ацэнкі:

[
  {
    "question": "Where is order 48291?",
    "expected": "SHIPPED"
  },
  {
    "question": "Which warehouse fulfills order 48291?",
    "expected": "WH-17"
  },
  {
    "question": "Can order 48291 be cancelled?",
    "expected": false
  }
]

Тады старайцеся фіксаваць такія паказнікі:

Answer Accuracy
Groundedness
Retrieval Precision
Tool Selection Accuracy
Tool Success Rate
Task Success Rate
Recovery Rate
Hallucination Rate
Latency
Cost

Таблыца з рэзультатамі до і пасля дапамагае зрозумець адрысныя змяны:

                      Before    After
Answer Accuracy        72%      95%
Groundedness           69%      97%
Tool Success           81%      98%
Hallucination Rate     17%       3%

Цякож вы не толькі стверджуеце, што новы запрос працюе лепшая, але і практычна паказуеце гэта. Самэлькі тут інжынерыя ШЫ пачынае нарадзіцца сэродзевае з звычайной інжынерыяю програмнага забезпечэння:

Change
  ↓
Test
  ↓
Measure
  ↓
Compare
  ↓
Improve

Усе дзесяць шароў разам

Размясціце дзесяць шароў абоўсюды навакола LLM, і архітэктура будзе выглядаць так:

                         ┌──────────────────┐
                         │ Knowledge Graph  │
                         └────────┬─────────┘
                                  │
                         ┌────────▼─────────┐
                         │   RAG / Search   │
                         └────────┬─────────┘
                                  │
       Customer → Intent → Context Engine → LLM
                     ↑             │
                     │             ▼
                   Memory      Tool Selection
                     ↑             │
                     │             ▼
                     │          Validation
                     │             │
                     │             ▼
                     │        Real Systems
                     │             │
                     │             ▼
                     └─────── Feedback
                                   │
                                   ▼
                               Evaluation

Зверніце ўвагу на тое, чаго не сталася: мадэль не піддаўалася додатковай налаштовкі. Сістэма, якая яе абрамляе, паспела павыліцца.

Пытанні, якія трэба задаць перш чым звынувачваць мадэль

Першы інстынкт у разе галюцынацыі — часта гэта лепшая мадэль. Інодзе гэта правда. Але спачатку трэба працаваць за чыртком перагляду.

  1. Чы быў заданы правільны кантэкст?
  2. Чы была запрашана правільная інфармацыя?
  3. Чы былы адключаны нерэлевантныя матэрыялы?
  4. Чы можа структураваныя знанні даўці адпаведны адпаведнік?
  5. Чы можа інструмент прачытаць рэальны стан сістэмы?
  6. Чы быў перакананы выход мадэлі?
  7. Чы факты былі выдзелены ад логічных выводам?
  8. Чы сістэма навучылася на пакульніх запусках?
  9. Чы былі наданы доказы?
  10. Чы рэзультаты былі вымераны?

Гэтыя перагляды зазвычай ведуць да чагосьць, што ў меру дэшэўшае, безпечнейшае і лёгкайшае для кантролю, чым додатковая налаштовка.

Мадэль — толькі адна з складовых

Корыстныя зябры:

              ┌───────────────────┐
              │ Knowledge + RAG   │
              └─────────┬─────────┘
                        ↓
Customer → Context → LLM → Tools → Real World
            ↑         ↓      ↓
          Memory   Reasoning Validation
            ↑         ↓
            └──── Feedback
                    ↓
                Evaluation

LLM стварае можлівасці. Усе наваколле яго суплікуюць факты, кантэкст, абмежэнні, інструменты, парадакты, памяць і адзвечанні, і самэ гэта робіць весь прыемлівым.

Галюцінаціі частаюць больш проблемай дзеяння сістэмы, чым проблемай самага модэлю. Лепшы кантэкст, лепшыя знанні, лепшыя інструменты, парадакты, перакананыя выходны даныя і навучэнне на адваротнае даўаць можа больш, чым новы цыкл адучэння. Практычны вопыт пераходзіць з таго, канферэнтны модэль выкорыстоўваць, да таго, што модэль павінна ведаць, што яна можа рабіць, і як вы з’ясавіце, чы робіць яна правільна.