本文将完整示例说明如何使用 Claude 构建可搜索内部知识库的 RAG 聊天机器人,规模为约 5,000 份日文文档。内容还包括约 30 行代码及月度运营成本估算。
总体概览
- 将文档转换为嵌入向量(text-embedding-3-large)
- 使用同一模型将用户问题转换为向量,并检索排名前 5 的结果
- 将检索到的 context 发送给 Claude Sonnet 4.6 生成回答
- 通过 Prompt caching 将重复调用成本降低 90%
1) 嵌入文档(仅一次)
embed.py
# 1) 5,000 件の社内文書を埋め込みベクトル化
from openai import OpenAI
# 埋め込みは Kunavo では提供していません(/v1/embeddings は実装済みの
# ワイヤフォーマットですが、有効なモデルがないため呼ぶと失敗します)。
# 埋め込みは OpenAI に直接、生成は Kunavo に — クライアントは 2 つ持ちます。
embedder = OpenAI(api_key="sk-...") # OpenAI 本家
kunavo = OpenAI(
api_key="sk-kn-...",
base_url="https://api.kunavo.com/v1",
)
documents = load_documents() # [{id, text, metadata}, ...]
# バッチ 100 件ずつで埋め込みを呼ぶ
batches = [documents[i:i+100] for i in range(0, len(documents), 100)]
all_vectors = []
for batch in batches:
resp = embedder.embeddings.create(
model="text-embedding-3-large",
input=[d["text"] for d in batch],
)
all_vectors.extend(resp.data)
# Postgres + pgvector に保存(または Pinecone, Qdrant など)
save_to_vector_db(documents, all_vectors)5,000 份 × 平均 500 个令牌,即 250 万个令牌。由于 Kunavo 不提供嵌入服务,因此只有这一步会直接向 OpenAI 付费——单价请在 OpenAI 的价格页面确认。这里不写数字,是因为如果写下自己不销售的产品价格,即使价格过时,也没有人会注意到。该处理只需运行一次,然后将结果保存到 pgvector。
2) 查询时的检索与回答生成
query.py
# 2) ユーザー質問 → 関連文書を検索 → Claude に投げて回答
def answer(question: str) -> str:
# 質問を埋め込み化
q_embed = embedder.embeddings.create( # 埋め込みは OpenAI 直
model="text-embedding-3-large",
input=[question],
).data[0].embedding
# 上位 5 件を検索
relevant = vector_search(q_embed, top_k=5)
# Claude に context + question を渡す
context = "\n\n---\n\n".join(d["text"] for d in relevant)
resp = kunavo.chat.completions.create( # 生成は Kunavo
model="claude-sonnet-4-6",
messages=[
{
"role": "system",
"content": (
"あなたは社内ナレッジ ベースをもとに正確に答えるアシスタントです。"
"提供された context にない情報については「情報がありません」と答えてください。"
),
},
{"role": "user", "content": f"# Context\n{context}\n\n# 質問\n{question}"},
],
max_tokens=800,
)
return resp.choices[0].message.content每次查询使用的令牌:问题嵌入(约 $0.000005)+ Claude Sonnet 4.6 输入约 5K 个令牌(context)× $1.20/1M = $0.006 + 输出约 500 个令牌 × $6.00/1M = $0.003。每次查询约 $0.009(约 1.4 日元)。
3) 通过 Prompt caching 进一步降低成本
由于每次都会发送相同的系统提示,因此 Anthropic prompt caching 会生效:
cache.py
# 3) Cache_control で再呼び出しコストを 90% 削減
# 同じ context(社内ドキュメント)を何度も使うので、Anthropic prompt caching が効く
resp = client.chat.completions.create(
model="claude-sonnet-4-6",
messages=[
{
"role": "system",
"content": [{
"type": "text",
"text": SYSTEM_PROMPT_AND_GUIDELINES, # 安定したシステムプロンプト
"cache_control": {"type": "ephemeral"},
}],
},
{"role": "user", "content": f"# Context\n{context}\n\n# 質問\n{question}"},
],
)
# 2回目以降の同じシステムプロンプトはキャッシュヒット → 入力料金の 10%如果系统提示稳定包含 3,000 个令牌且始终相同,则从第二次起,该部分输入将按10% 的价格计费。实测每次查询可降至约 $0.004(约 0.6 日元)。
月度运营成本估算
| 用量 | 成本 | 备注 |
|---|---|---|
| 初始嵌入 | $0.25 | 一次性 |
| 每天 1,000 次查询 | 约 $270/月 | 无 caching |
| 每天 1,000 次查询 | 约 $110/月 | 有 caching |
| 每天 10,000 次查询 | 约 $1,100/月 | 有 caching,Slack 机器人规模 |
日语特有的注意事项
- 令牌消耗:日语有时会消耗英语 2-3 倍的令牌(原因在于汉字和假名的编码方式)。将 context 从 5K 缩减到 3K,用检索精度取胜吧
- 嵌入模型:text-embedding-3-large 支持多语言,日语精度也足够。如果内部术语较多,建议另行维护同义词词典
- Claude vs Gemini 2.5 Pro:长文本摘要和引用方面 Claude 更严谨,检索范围方面 Gemini 2.5 Pro 更广。通常应从 Sonnet 4.6 开始,并根据需要升级到 Opus 4.7
- 防止幻觉:在系统提示中明确写明:“如果 context 中没有相关信息,就回答‘没有相关信息’”。如果仍有遗漏,可收紧 max_tokens,并要求返回来源文档 ID,再在 UI 中显示来源链接
上线检查清单
- 嵌入索引更新流程(通过 cron 每日、每周重建)
- 失败时的回退方案(Claude → Gemini 2.5 Flash 等两级方案)
- 速率限制与成本上限(在 /app/keys 中为每个密钥设置每日 $50 等上限)
- 日志与监控(通过 usage 仪表板追踪每日成本)
- 《特定商业交易法》(面向日本客户)— /legal/tokutei-shoutorihiki
开始使用请先免费注册。从 $10 起充值并按用量付费,详情请参阅 /docs/quickstart 或 /docs/caching。