Retour au blog
Guide d’implémentation·25 mai 2026·8 min de lecture

Construire un chatbot RAG en japonais avec Claude — une base de connaissances de 5 000 documents en 30 lignes

Implémentation complète d’un RAG rendant consultables 5 000 documents internes avec Claude Sonnet 4.6. Environ 0,9 yen par requête après application du prompt caching. Les embeddings ne sont pas fournis par Kunavo et cette seule étape est facturée directement par OpenAI. Inclut la consommation de tokens propre au japonais, les mesures contre les hallucinations et la checklist de mise en production.

Exemple complet montrant comment créer un chatbot RAG permettant d’effectuer des recherches dans une base de connaissances interne avec Claude, avec une implémentation portant sur environ 5 000 documents en japonais. Nous le publions avec environ 30 lignes de code et une estimation des coûts mensuels d’exploitation.

Vue d’ensemble

  1. Vectoriser les documents sous forme d’embeddings (text-embedding-3-large)
  2. Vectoriser la question de l’utilisateur avec le même modèle et rechercher les 5 premiers résultats
  3. Envoyer le context récupéré à Claude Sonnet 4.6 pour générer la réponse
  4. Réduire de 90 % le coût des appels répétés grâce à la mise en cache des prompts

1) Créer les embeddings des documents (une seule fois)

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 documents × 500 tokens en moyenne, soit 2,5 millions de tokens. Les embeddings ne sont pas fournis par Kunavo ; seule cette étape est donc facturée directement par OpenAI — consultez la page tarifaire d’OpenAI pour connaître le prix unitaire. Si aucun chiffre n’est indiqué ici, c’est parce que le prix d’un produit que nous ne vendons pas peut devenir obsolète sans que personne ne s’en aperçoive. Exécutez ce traitement une seule fois, puis enregistrez le résultat dans pgvector.

2) Recherche et génération de réponses au moment de la requête

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

Tokens utilisés pour chaque requête : embedding de la question (~0,000005 $) + environ 5 K tokens d’entrée de Claude Sonnet 4.6 (context) × 1,20 $/1M = 0,006 $ + environ 500 tokens de sortie × 6,00 $/1M = 0,003 $. Environ 0,009 $ par requête (environ 1,4 yens).

3) Réduire encore les coûts grâce à la mise en cache des prompts

Le même prompt système étant envoyé à chaque fois, la mise en cache des prompts d’Anthropic est efficace :

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%

Si le prompt système de 3 000 tokens reste identique, à partir de la deuxième requête, l’entrée de cette partie est facturée à 10 % du tarif. Les mesures montrent que le coût descend jusqu’à environ 0,004 $ par requête (environ 0,6 yen).

Estimation des coûts mensuels d’exploitation

UtilisationCoûtRemarques
Embeddings initiaux$0.25Une seule fois
1 000 requêtes/jourEnviron 270 $/moisSans mise en cache
1 000 requêtes/jourEnviron 110 $/moisAvec mise en cache
10 000 requêtes/jourEnviron 1 100 $/moisAvec mise en cache, à l’échelle d’un bot Slack

Points d’attention propres au japonais

  • Consommation de tokens : le japonais peut consommer 2 à 3 fois autant de tokens que l’anglais (pour des raisons liées à l’encodage des kanji et des kana). Réduisez le context de 5 K à 3 K et misez sur la précision de la recherche
  • Modèle d’embeddings : text-embedding-3-large prend en charge plusieurs langues et offre une précision suffisante en japonais. Si votre corpus contient beaucoup de termes internes, il est recommandé de gérer séparément un dictionnaire de synonymes
  • Claude contre Gemini 2.5 Pro : Claude est plus rigoureux pour les résumés longs et les citations, tandis que Gemini 2.5 Pro offre une recherche plus large. La méthode habituelle consiste à commencer par Sonnet 4.6 et à passer à Opus 4.7 si nécessaire
  • Prévention des hallucinations : indiquez explicitement dans le prompt système : « si l’information ne figure pas dans le context, répondre “information indisponible” ». Si des omissions persistent, réduisez max_tokens, faites renvoyer l’ID du document source et affichez le lien de la source dans l’interface

Liste de contrôle avant la mise en production

  • Flux de mise à jour de l’index d’embeddings (reconstruction quotidienne et hebdomadaire avec cron)
  • Solution de repli en cas d’échec (Claude → Gemini 2.5 Flash, par exemple, en deux niveaux)
  • Limites de débit et plafond de coûts (caps quotidiens de 50 $ par clé, par exemple, dans /app/keys)
  • Journaux et supervision (suivi quotidien des coûts dans le tableau de bord usage)
  • Loi japonaise sur les transactions commerciales spécifiées (clients au Japon) — /legal/tokutei-shoutorihiki

Pour commencer, inscrivez-vous gratuitement. Rechargez à partir de 10 $ et commencez à utiliser le service à la consommation ; consultez /docs/quickstart ou /docs/caching pour plus de détails.