一句话摘要
用 Claude 搭建 RAG 系统的方法
如何用 Claude 搭建一个 RAG 系统:一个跑在你自有数据上的 AI(完整指南) 2026 年 7 月 11 日 · 18 分钟阅读 · 查看原文 ↗ Claude AI Obsidian
去向 Claude 询问你的公司、你的笔记或你的文件,它一脸茫然。它从没见过这些东西。它只知道训练时学到的内容,而你的东西不在那里面。
一个 RAG 系统能解决这个问题。Claude 不再凭记忆作答,而是先在你的文档里查找,抓取相关的部分,然后根据它真正找到的内容来回答。你的数据、它的来源,不做猜测。
为什么这比直接把文件粘贴进聊天强:
它能扩展。你整个知识库塞不进一个聊天窗口。RAG 存下所有内容,只为每个问题拉取所需的部分。
它更便宜。粘贴一个文件意味着 Claude 每次提问都要把整份东西重读一遍。RAG 只读一次,之后只取相关部分。与其每次都发送一份 10,000 token 的手册,它可能只发送你需要的那个精确段落——500 token。真实部署能削减 80% 甚至更多的 token 用量。
它更精准。把一个巨大的文本墙喂给模型,它会丢掉中间部分的细节。递给它几个精确的块,答案会更准确。
它保持最新。更新你的文件一次,系统就会使用新版本。不用重新粘贴。
读完这份指南,你将拥有一个跑在你自有文件上的系统,一步一步来,不需要博士学位。
你需要什么
在碰任何代码之前,先列全清单。好消息:这个版本只需要一个 API key,其他所有东西都在你自己的机器上免费运行。
Python 3.9 或更新版本。要检查你是否装了,打开你的终端(Mac 上是 Terminal,Windows 上是 Command Prompt),输入 python --version。如果你看到类似 3.11 的东西,就没问题。如果没有,从 python.org 下载并运行安装程序。在 Windows 上,安装时勾选「Add Python to PATH」这个框,否则下面这些命令跑不起来。
一个 Claude API key,加上一点小额余额。这是整份指南唯一需要的 key 和唯一的钱。以下是精确路径,一步一步点:
前往 platform.claude.com,在那里登录(或注册)。
API 需要正余额才能运行,所以先充钱。出现提示时,选择这些额度是给你自己还是给公司,然后你会落到支付页面。选 $5 的「Starting out」选项。这足够了:本指南其他一切都是免费且本地的,所以 Claude 是唯一花钱的东西,而且每个问题只花你不到一美分。额度购买后一年过期。
付完款后,你会落到 Console 仪表盘。你应该能在左上角「Organization credits」下面看到你的余额(例如 $5.00)。
现在拿 key。点 Get API key(右上角),然后 Create Key。给它起任何你喜欢的名字(例如 my-rag-key),workspace 保持 Default。点 create,然后复制它显示给你的字符串。它以 sk-ant- 开头,而且你只能看到一次,所以先把它粘贴到某个安全的地方放一会儿。
整个设置就是这些。
第 1 步:添加你的 key,加载你的文件
建项目文件夹。在桌面上新建一个文件夹,命名为 rag-project。所有东西都放这里。
打开你的终端。Mac 上:Cmd+Space,输入 Terminal,回车。Windows 上:开始按钮,输入 cmd,回车。
把终端指向你的文件夹。输入 cd 加一个空格,然后把 rag-project 文件夹拖到终端窗口上,按回车。下面每条命令都在这个文件夹里运行。
安装工具。把下面这段粘贴进终端并按回车(第一次运行可能要等一分钟):
pip install anthropic chromadb sentence-transformers pypdf python-dotenv
如果你遇到 pip: command not found,用 pip3 代替 pip。当终端显示出一行没有红色错误的新提示符时,就完成了。
创建你的代码文件。在 rag-project 里,创建一个空文件,命名必须为 rag.py。用任意文本编辑器打开它。
创建你的 key 文件。在同一个文件夹里,创建一个命名必须为 .env 的文件(以点开头,前面没有名字)。把下面这行粘贴进去,= 后面放你设置时创建的真正 key,没有空格、没有引号:
ANTHROPIC_API_KEY=sk-ant-paste-your-real-key-here
把 key 放在 .env 里而不是代码里,意味着即使你分享这个脚本或把它放到 GitHub 上,它也不会泄露。
加载 key。把这行放到 rag.py 顶部:
import os
from dotenv import load_dotenv
load_dotenv() # reads your .env file
api_key = os.getenv("ANTHROPIC_API_KEY")
创建你的知识库。在 rag-project 里,创建一个名为 documents 的文件夹。把任何 .txt、.md 或 .pdf 文件丢进去:你的笔记、一份产品文档、会议纪要,任何东西。
8.1. 如果你还没有文件,用这个测试文件。在 documents 文件夹里创建 notes.txt,然后粘贴这段:
Project Northstar is our internal tool for tracking customer feedback. It was launched in March 2026 and is maintained by the platform team. The lead engineer is Dana Reyes. Feedback is reviewed every Friday. Northstar replaced the old spreadsheet system we used through 2025.
(译:Project Northstar 是我们追踪客户反馈的内部工具。它于 2026 年 3 月上线,由平台团队维护。首席工程师是 Dana Reyes。反馈每周五审阅。Northstar 取代了我们用到 2025 年的旧电子表格系统。)
最后你会向 Claude 询问 Northstar,看它从这个确切文件里作答。
添加读取文件的代码。在第 7 步代码的下方,放进 rag.py:
from pathlib import Path
from pypdf import PdfReader
def load_documents(folder="documents"):
docs = []
for file in Path(folder).iterdir():
if file.suffix in [".txt", ".md"]:
text = file.read_text(encoding="utf-8")
docs.append({"source": file.name, "text": text})
elif file.suffix == ".pdf":
reader = PdfReader(str(file))
text = "\n".join(page.extract_text() or "" for page in reader.pages)
docs.append({"source": file.name, "text": text})
return docs
documents = load_documents()
print(f"Loaded {len(documents)} document(s).")
运行它。保存 rag.py,然后在终端里:
python rag.py
你应该看到:
Loaded 1 document(s)
如果你看到 Loaded 0 document(s),说明 documents 文件夹是空的或位置不对。它必须直接位于 rag-project 里,挨着 rag.py。
第 2 步:把文件切成块
现在每个文件是一大块文本。在我们能搜索它之前,需要把它切成更小的片段,叫做 chunk(块)。原因如下:当有人提问时,系统找到匹配的块,只把这些块发给 Claude。如果你的块是整份 50 页的文档,你发送的太多了。如果它们是单个句子,又丢失了上下文。小段落是最佳点。
添加分块代码。在第 10 步代码的下方,放进 rag.py:
def chunk_text(text, chunk_size=500, overlap=100):
words = text.split()
chunks = []
start = 0
while start < len(words):
end = start + chunk_size
chunk = " ".join(words[start:end])
chunks.append(chunk)
start = end - overlap # step back a little so chunks overlap
return chunks
这里有两个数字要理解,用大白话说:
chunk_size=500 意味着每个块大约 500 个词。大到能装下一个完整的想法,小到能保持精确。
overlap=100 意味着每个块会重复它前面那个块的最后 100 个词。这很重要,因为一个答案可能正好落在两个块交界的那条线上。没有重叠,一句被从中间劈开的句子就可能丢失。重叠确保没有想法从裂缝中漏掉。
把每个文档变成块。在下面加上这段:
all_chunks = []
for doc in documents:
for chunk in chunk_text(doc["text"]):
all_chunks.append({"source": doc["source"], "text": chunk})
print(f"Created {len(all_chunks)} chunk(s) from {len(documents)} document(s).")
注意每个块都带着它的来源(它来自的那个文件名)。我们全程都保持这个附着,这样之后 Claude 回答时,能告诉你答案来自哪个文件。
运行它。保存 rag.py,然后在终端里:
python rag.py
你应该看到类似这样的东西:
Loaded 1 document(s).
Created 1 chunk(s) from 1 document(s).
那个小测试文件只变成一个块,因为它很短。真实文档会产生很多块。如果你把一个长 PDF 丢进文件夹,你可能会看到几十甚至几百个块,那正是你想要的。
第 3 步:把块变成嵌入(embeddings)
这一步让计算机能按语义搜索,而不是按精确的词语。每个块被转换成一个数字列表(一个 embedding),捕捉它讲的是什么。语义相近的块最终会得到相近的数字。之后,当一个问题进来时,我们也把问题变成数字,然后找最接近的匹配。
做这件事的模型在你本机本地运行。它下载一次,之后离线、免费工作,而且你的文件永远不会离开你的电脑。
加载嵌入模型。在第 2 步代码的下方,放进 rag.py:
from sentence_transformers import SentenceTransformer
print("Loading the embedding model (first run downloads it, about 90 MB)...")
embedder = SentenceTransformer("all-MiniLM-L6-v2")
你第一次运行这个的时候,它会下载模型,所以给它一点时间。之后每次运行都是瞬间的,因为它已经在你机器上了。
把每个块变成嵌入。在下面加上这段:
chunk_texts = [chunk["text"] for chunk in all_chunks]
embeddings = embedder.encode(chunk_texts)
print(f"Created {len(embeddings)} embedding(s).")
print(f"Each embedding is a list of {len(embeddings[0])} numbers.")
embedder.encode(...) 接收你的块文本列表,为每个块返回一个嵌入。要做的就这么多。
运行它。保存 rag.py,然后在终端里:
python rag.py
第一次运行会暂停一会儿等模型下载,然后你应该看到类似:
Loaded 1 document(s).
Created 1 chunk(s) from 1 document(s).
Loading the embedding model (first run downloads it, about 90 MB)...
Created 1 embedding(s).
Each embedding is a list of 384 numbers.
那一行「384 numbers」让整个想法变得可见:你的文本现在是一行计算机可以比较的数字。你自己不需要去读或理解那些数字。下一步里的数据库会替你处理所有比较。
如果下载因为连接错误而失败,只要再运行一次命令就行。它会从断开的地方继续。
第 4 步:把所有东西存进你的向量数据库
现在我们把块和它们的嵌入放进 Chroma,你的本地数据库。这就是让搜索变快的原因:与其每次手动把问题跟每个块比较,Chroma 把它们存好待命,替你完成匹配。它保存到你机器上的一个文件夹,所以你只需要构建一次。
设置数据库。在第 3 步代码的下方,放进 rag.py:
import chromadb
client = chromadb.PersistentClient(path="chroma_db")
collection = client.get_or_create_collection("my_documents")
PersistentClient(path="chroma_db") 告诉 Chroma 保存到一个叫 chroma_db 的文件夹(它会自动创建,就在你的脚本旁边)。因为它保存到磁盘,所以脚本跑完后你的数据仍然存在。一个 collection 就是你的块所居住的那个带名字的盒子。
把你的块加进数据库。在下面加上这段:
collection.add(
ids=[str(i) for i in range(len(all_chunks))],
embeddings=[emb.tolist() for emb in embeddings],
documents=[chunk["text"] for chunk in all_chunks],
metadatas=[{"source": chunk["source"]} for chunk in all_chunks],
)
print(f"Stored {collection.count()} chunk(s) in the database.")
下面是每一行交给 Chroma 的东西,用大白话说:ids 给每个块一个唯一标签(0, 1, 2...),embeddings 是第 3 步的数字,documents 是实际的块文本,metadatas 则带上文件名,这样我们之后能展示来源。Chroma 把这四样绑在一起保存。
运行它。保存 rag.py,然后在终端里:
python rag.py
你应该看到:
Stored 1 chunk(s) in the database.
有一点要为之后记住。现在你每次运行脚本,它都会再次添加这些块,所以计数在重复运行时会上涨(1,然后 2,然后 3...)。在我们构建的过程中这没关系。要清空重来,删掉 chroma_db 文件夹再运行一次。在最终版本里我们会正确处理这一点,避免重复累加。
第 5 步:搜索你的文档
这是 RAG 的「检索」部分,也就是名字里的 R。我们拿一个问题,用和块同样的方式把它变成嵌入,然后问 Chroma 要语义最接近的块。那些匹配的块,就是我们下一步要交给 Claude 的东西。
添加搜索函数。在第 4 步代码的下方,放进 rag.py:
def search(question, n_results=3):
question_embedding = embedder.encode([question])[0]
results = collection.query(
query_embeddings=[question_embedding.tolist()],
n_results=n_results,
)
return results
它做了什么,逐行用大白话说:它用你处理块时用的同一个模型,把问题变成数字(这很重要,两边必须说同一种「数字语言」),然后问 Chroma 要最接近的匹配。n_results=3 的意思是「给我 3 个最相关的块」。三是很好的默认值:上下文够用,又不会多到浪费 token。
试一次搜索。在下面加上这段来测试:
question = "Who runs Northstar and when is feedback reviewed?"
results = search(question)
for i, doc in enumerate(results["documents"][0]):
source = results["metadatas"][0][i]["source"]
print(f"\n--- Match {i+1} (from {source}) ---")
print(doc)
这会针对你的数据库运行一个真实问题,并打印它找到的块,每个都带着它来自的文件名。
运行它。保存 rag.py,然后在终端里:
python rag.py
用 Northstar 测试文件,你应该看到它拉回匹配的块,类似:
--- Match 1 (from notes.txt) ---
Project Northstar is our internal tool for tracking customer feedback. It was launched in March 2026 and is maintained by the platform team. The lead engineer is Dana Reyes. Feedback is reviewed every Friday. Northstar replaced the old spreadsheet system we used through 2025.
注意刚刚发生了什么:你的问题用了「who runs」和「reviewed」这些词,但文件里写的是「lead engineer」和「reviewed every Friday」。它还是匹配上了,因为搜索靠的是语义,而不是精确的词语。这正是嵌入的全部意义,也正是它为什么胜过对你文件做普通的关键词搜索(Ctrl+F)。
如果你有更多文件,你会看到来自所有文件里排名前 3 的块,按匹配紧密度排序。
第 6 步:让 Claude 根据它找到的内容作答
这是「生成」部分,RAG 里的 G。我们拿第 5 步的块,连同问题一起交给 Claude Opus 4.8,并告诉它只用那段上下文来回答。这正是阻止它猜测的东西:Claude 根据你的文件作答,而不是凭自己的记忆,并告诉你它用了哪个文件。
添加回答函数。在第 5 步代码的下方,放进 rag.py:
import anthropic
claude = anthropic.Anthropic(api_key=api_key)
def answer(question):
results = search(question)
chunks = results["documents"][0]
sources = [m["source"] for m in results["metadatas"][0]]
context = ""
for i, chunk in enumerate(chunks):
context += f"[From {sources[i]}]\n{chunk}\n\n"
message = claude.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system=(
"You answer questions using only the context provided. "
"If the answer is not in the context, say you don't know. "
"Always mention which file your answer came from."
),
messages=[
{
"role": "user",
"content": f"Context:\n{context}\nQuestion: {question}",
}
],
)
return message.content[0].text
这里发生了什么,用大白话说:我们搜索相关块,把它们粘成一个上下文块(每个都标着它的文件名),然后把那个块加上问题发给 Claude。system 指令是关键部分。它告诉 Claude 三件事:只用上下文作答、当答案不在里面时就承认、并说出来源文件。正是这三条规则让答案可信,而不是编造。
model="claude-opus-4-8" 是确切的模型名(连字符,不是点)。max_tokens=1024 给答案长度设了上限。
问一个问题。在下面加上这段:
question = "Who runs Northstar and when is feedback reviewed?"
print(answer(question))
运行它。保存 rag.py,然后在终端里:
python rag.py
你应该得到一个基于你文件构建的真实答案,类似:
Dana Reyes is the lead engineer who runs Project Northstar, and feedback is reviewed every Friday. (Source: notes.txt)
(译:Dana Reyes 是负责 Project Northstar 的首席工程师,反馈每周五审阅。(来源:notes.txt))
这就是一个完整运转的 RAG 系统。Claude 在训练时从没见过这个文件,它不可能知道 Dana Reyes 是谁,然而它答对了,并准确告诉你答案来自哪里。问它一些不在你文件里的东西,它会说不知道,而不是编一个答案。那个「我不知道」是一个特性,不是失败:它是一个你可以信任的工具和一个会瞎猜的工具之间的区别。
第 7 步:把它变成你真正能用的东西
现在你每次想问点什么,都得改代码并重跑整个脚本。更糟的是,每次运行都会重读你的文件并把它们重新加进数据库,于是块不断堆积。让我们把两个问题都修掉:只构建数据库一次,然后让你在一个循环里提问,直接在终端里输入。
修复重复添加。找到第 4 步里添加块的那段代码(collection.add(...) 那部分),把它替换成这个版本,只在数据库为空时才构建:
if collection.count() == 0:
collection.add(
ids=[str(i) for i in range(len(all_chunks))],
embeddings=[emb.tolist() for emb in embeddings],
documents=[chunk["text"] for chunk in all_chunks],
metadatas=[{"source": chunk["source"]} for chunk in all_chunks],
)
print(f"Stored {collection.count()} chunk(s) in the database.")
else:
print(f"Database already has {collection.count()} chunk(s), skipping rebuild.")
现在重活(读文件、生成嵌入、填充数据库)只在第一次发生。之后的运行直接跳到回答。
添加提问循环。在 rag.py 最底部,把第 6 步那单个测试问题替换成这个:
print("\nAsk a question about your documents (or type 'quit' to exit).\n")
while True:
question = input("You: ")
if question.lower() in ["quit", "exit"]:
break
print("\nClaude: " + answer(question) + "\n")
input("You: ") 等待你输入一个问题并按回车。while True 让它一直跑,这样你想问多少就问多少。输入 quit 就停止。
运行它。保存 rag.py,然后在终端里:
python rag.py
现在你可以直接跟你的文件对话了:
Ask a question about your documents (or type 'quit' to exit).
You: who is the lead engineer on Northstar?
Claude: The lead engineer on Project Northstar is Dana Reyes. (Source: notes.txt)
You: what did it replace?
Claude: Northstar replaced the old spreadsheet system used through 2025. (Source: notes.txt)
You: quit
这就是你完成的 RAG 系统。它读你的文件一次,记住它们,并按需回答关于它们的问题,每次都带上来源。
添加新文件时要了解的一点。因为数据库现在只构建一次,往 documents 里丢新文件不会自动出现。要加载新文件,删掉 chroma_db 文件夹再运行一次脚本。它会用文件夹里的所有东西从零重建。
可选:在浏览器里给它一个聊天窗口
终端能用,但如果你想要一个真正的聊天窗口,Streamlit 用大约 20 行就能加一个。
安装它。在终端里:
pip install streamlit
在同一个文件夹里创建 app.py 并粘贴下面这段。它复用了你 rag.py 里的 answer 函数:
import streamlit as st
from rag import answer
st.title("Chat with your documents")
if "history" not in st.session_state:
st.session_state.history = []
question = st.chat_input("Ask about your files...")
if question:
reply = answer(question)
st.session_state.history.append((question, reply))
for q, a in st.session_state.history:
st.chat_message("user").write(q)
st.chat_message("assistant").write(a)
运行它。在终端里(注意:是 streamlit run,不是 python):
streamlit run app.py
它会在浏览器里自动打开一个聊天窗口。输入一个问题,得到一个带来源的答案,就像终端里一样,但更好看。
一个注意点:要让它工作,第 7 步的提问循环需要不在 import 时运行。把 rag.py 底部的那个循环包进 if name == " main ": 里,这样它只在你直接运行 rag.py 时触发,而不是在 app.py 导入它时触发。
让它也能回答一般性问题
如果你还想让它回答一般性问题。现在系统只根据你的文件作答,所以像「委内瑞拉的首都是什么?」这样的问题会得到「那不在文档里」,尽管 Claude 知道答案。如果你想让它回退到自己的知识,打开 rag.py,找到第 6 步里 system=(...) 那段,把这一行:
"If the answer is not in the context, say you don't know. "
换成这个:
"If the answer is not in the context, answer from your own general knowledge but say you're doing so. "
保存并重跑。现在它先从你的文件里作答,文件覆盖不到时就回退到一般知识,并告诉你它用的是哪一种。
收尾
你刚刚构建了一个能工作的 RAG 系统。它读你自己的文件、找到相关的部分、并让 Claude 根据它们作答,每次都带上确切来源。同一套设置可以从几篇笔记扩展到你的整个知识库。
从这里开始,它可以指向任何地方:你的 Obsidian 库、你的工作文档、你保存的调研。把文件丢进去,重建一次,然后开始提问。你在这里学到的一切——块、嵌入、搜索、回答——正是你见过的每个「与你的文档对话」工具背后的同一套骨架。
如果这对你有用,去我的主页关注我。我写科技、AI,以及真正跑得起来的系统。
Ciao,
@undefinedKi
Prompts
import chromadb
client = chromadb.PersistentClient(path="chroma_db")
collection = client.get_or_create_collection("my_documents")
python rag.py
question = "Who runs Northstar and when is feedback reviewed?"
print(answer(question))
python rag.py
from pathlib import Path
from pypdf import PdfReader
def load_documents(folder="documents"):
docs = []
for file in Path(folder).iterdir():
if file.suffix in [".txt", ".md"]:
text = file.read_text(encoding="utf-8")
docs.append({"source": file.name, "text": text})
elif file.suffix == ".pdf":
reader = PdfReader(str(file))
text = "\n".join(page.extract_text() or "" for page in reader.pages)
docs.append({"source": file.name, "text": text})
return docs
documents = load_documents()
print(f"Loaded {len(documents)} document(s).")
def search(question, n_results=3):
question_embedding = embedder.encode([question])[0]
results = collection.query(
query_embeddings=[question_embedding.tolist()],
n_results=n_results,
)
return results
python rag.py
from sentence_transformers import SentenceTransformer
print("Loading the embedding model (first run downloads it, about 90 MB)...")
embedder = SentenceTransformer("all-MiniLM-L6-v2")
print("\nAsk a question about your documents (or type 'quit' to exit).\n")
while True:
question = input("You: ")
if question.lower() in ["quit", "exit"]:
break
print("\nClaude: " + answer(question) + "\n")
streamlit run app.py
collection.add(
ids=[str(i) for i in range(len(all_chunks))],
embeddings=[emb.tolist() for emb in embeddings],
documents=[chunk["text"] for chunk in all_chunks],
metadatas=[{"source": chunk["source"]} for chunk in all_chunks],
)
print(f"Stored {collection.count()} chunk(s) in the database.")
pip install streamlit
question = "Who runs Northstar and when is feedback reviewed?"
results = search(question)
for i, doc in enumerate(results["documents"][0]):
source = results["metadatas"][0][i]["source"]
print(f"\n--- Match {i+1} (from {source}) ---")
print(doc)
python rag.py
chunk_texts = [chunk["text"] for chunk in all_chunks]
embeddings = embedder.encode(chunk_texts)
print(f"Created {len(embeddings)} embedding(s).")
print(f"Each embedding is a list of {len(embeddings[0])} numbers.")
if collection.count() == 0:
collection.add(
ids=[str(i) for i in range(len(all_chunks))],
embeddings=[emb.tolist() for emb in embeddings],
documents=[chunk["text"] for chunk in all_chunks],
metadatas=[{"source": chunk["source"]} for chunk in all_chunks],
)
print(f"Stored {collection.count()} chunk(s) in the database.")
else:
print(f"Database already has {collection.count()} chunk(s), skipping rebuild.")
def chunk_text(text, chunk_size=500, overlap=100):
words = text.split()
chunks = []
start = 0
while start < len(words):
end = start + chunk_size
chunk = " ".join(words[start:end])
chunks.append(chunk)
start = end - overlap # step back a little so chunks overlap
return chunks
pip install anthropic chromadb sentence-transformers pypdf python-dotenv
python rag.py
import streamlit as st
from rag import answer
st.title("Chat with your documents")
if "history" not in st.session_state:
st.session_state.history = []
question = st.chat_input("Ask about your files...")
if question:
reply = answer(question)
st.session_state.history.append((question, reply))
for q, a in st.session_state.history:
st.chat_message("user").write(q)
st.chat_message("assistant").write(a)
python rag.py
cd Desktop/rag-project
python rag.py
"If the answer is not in the context, say you don't know. "
ANTHROPIC_API_KEY=sk-ant-paste-your-real-key-here
import anthropic
claude = anthropic.Anthropic(api_key=api_key)
def answer(question):
results = search(question)
chunks = results["documents"][0]
sources = [m["source"] for m in results["metadatas"][0]]
context = ""
for i, chunk in enumerate(chunks):
context += f"[From {sources[i]}]\n{chunk}\n\n"
message = claude.messages.create(
model="claude-opus-4-8",
max_tokens=1024,
system=(
"You answer questions using only the context provided. "
"If the answer is not in the context, say you don't know. "
"Always mention which file your answer came from."
),
messages=[
{
"role": "user",
"content": f"Context:\n{context}\nQuestion: {question}",
}
],
)
return message.content[0].text
all_chunks = []
for doc in documents:
for chunk in chunk_text(doc["text"]):
all_chunks.append({"source": doc["source"], "text": chunk})
print(f"Created {len(all_chunks)} chunk(s) from {len(documents)} document(s).")
import os
from dotenv import load_dotenv
load_dotenv() # reads your .env file
api_key = os.getenv("ANTHROPIC_API_KEY")
"If the answer is not in the context, answer from your own general knowledge but say you're doing so. "
链接
python.org
platform.claude.com
rag.py
app.py
x.com/@undefinedKi
标签:# X # Claude # AI # Obsidian # 指南 # Rag 相关文章 如何记住你读到的一切(别再试了) 如果你需要记住它,它就不重要。如果它重要,你就会记住它。Aura AI Claude Obsidian
原文参考:https://maxed.wiki/posts/how-to-build-a-rag-system-using-claude-an-ai-that-runs-on-your-own-data-full-guide/ (Maxed.wiki,本页为站内中文整理)