FAQ ショートサーキット
LLM をバイパスする、SME 検証済みの質問→回答キャッシュ — 捏造防止ガードの手前に位置するため、保守的な除外条件の背後に置かれている。
FAQ キャッシュは、既知の質問に対して SME 検証済みの回答を返し、LLM・ファクトストア・リトリーバーを完全にバイパスします。これはレイテンシとコストの最適化であると同時に、高リスクなレイヤーでもあります。なぜなら、捏造防止ガードの 手前 に位置しているからです。誤ったショートサーキットは、下流のあらゆる安全チェックをスキップしてしまいます。
FAQ レイヤーは捏造防止の手前に位置するため、その除外条件は意図的に保守的になっています:構造化数値、競合他社、リアルタイム、期限切れ、無効化済み、および RESTRICTED の項目は決してショートサーキットされません。
配置される場所
/v1/ask ルート(service/api/routes.py)では、FAQ ルックアップが最初に実行されます:
# 1) FAQ short-circuit — on hit, never touches provider / fact store / retriever
hit = faq_cache.lookup(req.question, reference_date=ref)
if hit is not None:
return AskResponse(..., route="faq", answer=hit.answer, sources=[...])
# 2) miss -> normal workflow (anti-fabrication guard, dual channel, ...)
result = answer_question(req.question, store, provider, ...)lookup は純粋関数です(service/faq/faq_cache.py):境界判定のために parse_intent / clarify_scope を参照しますが、LLM・ファクトストア・リトリーバーには決して到達しません。マッチングは正規化済みの完全一致 / エイリアス一致のみ(NFKC + casefold + 空白の畳み込み + 末尾句読点の除去)で、ファジーマッチングや埋め込みによるマッチングは行いません。
保守的な除外条件
以下の いずれか に該当する場合、lookup はミス(None)を返します — これらの除外条件は、キャッシュインデックスを参照する 前 にチェックされます:
FAQ 項目
項目は SME による検証とバージョン管理を受けており、ヒットは自身の出典情報(FAQHit.source)を保持します:
{
"id": "what-is-ragspine",
"question": "RAGSpine 是什么?",
"aliases": ["What is RAGSpine?"],
"answer": "RAGSpine 是一个无框架的后端 RAG 引擎……",
"source": "internal/faq-handbook.md",
"version": 3,
"enabled": true,
"valid_from": "2026-01-01",
"valid_until": null,
"sensitivity": "INTERNAL"
}ヒットは route: "faq" を cache ブロック(hit、type、faq_id、version、source)とともに返します。トレースには cache_hit、faq_id、faq_version のみが記録され、回答テキストは決して記録されません。FAQ の JSON は環境変数 RAGSPINE_FAQ_SOURCE 経由で読み込みます。