Observability для RAG: какие события и контексты логировать
Свяжите route, версию и owner в receipt, а не превращайте каждый разговор в telemetry
Typed events, bounded context, redaction, terminal routes и reviewable ownership
OBSERVE-8 — авторский public synthetic workflow с явными ограничениями, не observability guarantee
observability для RAG, логи RAG, tracing RAG, telemetry AI-системы, RAG evaluation и safe event design

$ observe rag --contract OBSERVE-8
> bind: receipt / policy / index / route
> retrieve: eligible counts / permitted locators
> redact: payload fields / trace dimensions / retention
> inspect: versions / reason codes / terminal event
> route: answer / clarify / no-answer / deny / reviewObservability RAG — не просьба хранить каждый prompt, passage и completion навсегда. Его задача — дать owner точный инженерный ответ: какой route прошёл запрос, какие versioned evidence были eligible и где результат стал unsafe, недоступным или бесполезным?
Для этого нужен receipt, а не архив наблюдения. Receipt сохраняет связанные events, достаточные для проверки failure class, но минимизирует sensitive content. Широкую задачу продукта и внедрения покрывают RAG-системы и /ru/ai-specialist-armenia. Эта статья поддерживает их implementation criteria, не подменяет commercial intent и не обещает compliance.
Сначала определите наблюдаемое решение, потом выбирайте tracing tool
Начните с routes, по которым системе разрешено идти. Запрос может вернуть cited answer, попросить clarification, дать no-answer, отказать в доступе или ждать review. Для каждого route назовите owner, который способен определить, был ли он ожидаемым. Затем сохраните stable requestReceiptId, версии конфигурации и безопасные references на relevant inputs.
OBSERVE-8 связывает четыре records:
| Record | Минимальные поля | Зачем нужен |
|---|---|---|
| Request receipt | opaque ID, reference на authenticated scope, declared purpose, locale, received time | связывает events без копирования identity payload |
| Retrieval receipt | corpus/index version, policy version, eligible count, selected source locators | объясняет, какое evidence могло влиять на ответ |
| Generation receipt | model и prompt-template version, bounded token/count signals, output route | отделяет answer path от blocked или unavailable path |
| Review receipt | reason code, severity, decision owner, follow-up locator | делает human decision проверяемым без полного incident narrative |
Идентификатор не становится безопасным автоматически. Делайте cross-system IDs opaque, ограничивайте access к raw events и согласуйте retention с владельцем данных. Не записывайте prompt или excerpt документа только потому, что по полю удобно искать.
OBSERVE-8: event flow с границей redaction
Workflow отделяет product behavior от telemetry behavior. Authorization решает, можно ли начинать retrieval. Retrieval отдаёт counts и permitted locators, а не весь candidate payload. Отдельный шаг redaction удаляет или хеширует поля, которым не место в operational telemetry. Routing сохраняет, почему система ответила, уточнила, отказала, остановилась или отправила case на review.
request -> authorize -> retrieve eligible evidence -> compose bounded proposal
-> redact telemetry fields -> evaluate route -> answer | clarify | deny | review
-> link receipt IDs, versions and reason codesSource locator нуждается в независимом access rule: reviewer с доступом к trace всё ещё может не иметь права открыть underlying customer document. И наоборот, support dashboard не должен собирать secret из fragments events. Контроль доступа RAG раскрывает upstream eligibility, а метрики retrieval — измерения в declared evaluation set.
Выбирайте events, которые объясняют failure без записи разговора
Полезные events узкие и typed. Они фиксируют transition, version или reason code, а не неограниченный prose blob. Начать можно с такой event family:
| Event | Безопасные example signals | Не делать default field |
|---|---|---|
request.accepted | receipt ID, policy version, locale, declared route class | raw user prompt, email, account name |
retrieval.completed | eligible count, latency band, index revision, permitted locator IDs | full chunks, titles restricted documents |
evidence.selected | claim-to-locator count, freshness state, no-evidence reason | hidden ACL values или document text |
route.decided | answer / clarify / no-answer / deny / review, reason code | generated answer body |
tool.proposed | action type, allowlist decision, approval state | arguments с customer data |
review.closed | resolution category, owner reference, corrected config version | incident narrative в broad analytics |
Bounded samples сохраняйте только там, где их требует approved incident process. Храните sample отдельно, encrypt и access-control его, добавляйте expiry и отражайте решение в receipt. Это не то же самое, что незаметно класть полный content в каждый trace.
Проверьте один synthetic run от input до route
Используйте harmless fixture documents, чтобы проверить correlation до customer records. В synthetic example пользователь задаёт support question. Trusted scope разрешает одну current help collection; ожидаемый answer зависит от двух известных locators.
{
"requestReceiptId": "obs_demo_017",
"policyVersion": "rag-policy-2026-09",
"indexVersion": "help-current-42",
"events": [
{ "name": "request.accepted", "purpose": "support" },
{ "name": "retrieval.completed", "eligibleCount": 12, "selectedLocators": ["help:returns#v4", "help:delivery#v7"] },
{ "name": "evidence.selected", "coverage": "sufficient" },
{ "name": "route.decided", "route": "cited-answer", "reason": "permitted-current-evidence" }
]
}Важно не число 12, а связь: reviewer находит policy и index version, видит permitted locators и отличает проблему evidence от routing problem. Если locator стал stale, synthetic test должен ожидать review или no-answer, а не уверенный stale response.
Тестируйте telemetry contract рядом с RAG contract
Observability тоже может ломаться. Добавьте к evaluation set и release process такие проверки:
- Correlation. У каждого terminal route есть receipt ID, required version fields и bounded reason code.
- Minimization. Deliberately sensitive fixture не появляется в permitted event fields, queryable dimensions или exported dashboards.
- Authorization. Пользователь с trace access не открывает source locator без отдельного document policy.
- Completeness. Simulated timeout, empty retrieval, denied scope и review route выдают ожидаемый terminal event ровно один раз.
- Change detection. Изменение prompt, policy, index или tool даёт distinguishable version receipt; неизвестная version удерживает release для review.
- Operational use. Owner проходит один synthetic receipt от symptom к route и выбирает next action, не читая customer conversation.
Держите результаты раздельно по route и risk class. Один average latency или answer score не докажет, что denied retrieval был правильно denied, no-answer — честным, а новая index version не убрала evidence. Route distribution может подсказать расследование, но сам по себе не доказывает качество продукта.
Сделайте review и retention частью production boundary
До включения нового trace field назовите purpose, audience, retention period, storage boundary и removal path. Перепроверьте поле при изменении prompt template, tool call, collection или downstream analytics destination. Если команда не может объяснить, зачем поле нужно, не собирайте его default.
OBSERVE-8 — авторский public engineering pattern, а не specification observability product, юридическая рекомендация или утверждение о безопасности RAG. Используйте его для controlled architecture review: определите terminal routes, докажите telemetry minimization synthetic fixtures и назначьте owners для redaction, access, retention и release decisions. Для scoped implementation discussion начните с RAG-систем или /ru/ai-specialist-armenia.
require(receipt.id && receipt.policyVersion && receipt.indexVersion);
require(event.route && event.reasonCode && event.occurredAt);
require(telemetry.excludesSensitiveFixture && telemetry.locatorsAreAccessControlled);
require(testSet.timeout && testSet.empty && testSet.denied && testSet.review);
if (event.versionUnknown) route = "hold-for-review";
if (scope.denied) route = "deny-before-retrieval";
if (evidence.missing) route = "clarify-or-no-answer";
if (telemetry.redactionFailed) route = "stop-and-investigate";