Appearance
八、生成
8.1 生成原理
查找到相关数据之后,就可以将所有的数据放到和LLM交互的上下文当中,让LLM基于完整的上下文信息来进行生成。

8.2 基础生成
python
def rag_demo(client: MilvusClient, query):
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini")
# 检索相关数据
retrieval_res = hybrid_vector_search_example_rrf(client=client, query=query)
# 构建上下文
context = "\n".join([data["entity"]["text"] for data in retrieval_res])
message_list = [
{
"role": "system",
"content": "你是一个专业的法律问答机器人,请根据上下文回答问题,"
"当上下文无法回答问题时,请回答'根据上下文无法回答该问题'"
},
{
"role": "user",
"content": f"根据以下上下文回答问题:{context}\n问题:{query}"
}
]
res = llm.invoke(message_list)
print(res.content)8.3 LCEL构建RAG链
python
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
rag_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的AI助手。请根据以下上下文回答问题。\n\n上下文:{context}"),
("human", "{question}")
])
def format_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
rag_chain = (
{
"context": retriever | format_docs,
"question": RunnablePassthrough()
}
| rag_prompt
| llm
| StrOutputParser()
)
result = rag_chain.invoke("什么是RAG?")8.4 来源引用
python
from langchain_core.runnables import RunnableParallel
def format_docs_with_sources(docs):
formatted = []
for i, doc in enumerate(docs):
source = doc.metadata.get("source", "未知来源")
formatted.append(f"[来源{i+1}: {source}]\n{doc.page_content}")
return "\n\n---\n\n".join(formatted)
rag_chain_with_sources = (
RunnableParallel(
context=retriever | format_docs_with_sources,
question=RunnablePassthrough()
)
| rag_prompt | llm | StrOutputParser()
)到这里,我们已经逐步走完了RAG的六个环节。接下来把所有环节串在一起,跑通一个完整的端到端案例。
九、完整实战
9.1 端到端RAG
python
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_chroma import Chroma
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_core.output_parsers import StrOutputParser
from langchain_community.document_loaders import TextLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 1. 加载文档
documents = TextLoader("./documents/sample.txt").load()
# 2. 切分文档
splits = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=50,
separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""]
).split_documents(documents)
# 3. 创建向量存储
vectorstore = Chroma.from_documents(
documents=splits, embedding=OpenAIEmbeddings(), collection_name="rag_demo"
)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3})
# 4. 创建RAG链
rag_prompt = ChatPromptTemplate.from_messages([
("system", "你是一个有帮助的AI助手。请根据以下上下文回答问题。\n上下文:\n{context}"),
("human", "{question}")
])
llm = ChatOpenAI(model="gpt-4o-mini")
def format_docs(docs):
return "\n\n---\n\n".join([
f"[来源: {doc.metadata.get('source', '未知')}]\n{doc.page_content}"
for doc in docs
])
rag_chain = (
{"context": retriever | format_docs, "question": RunnablePassthrough()}
| rag_prompt | llm | StrOutputParser()
)
# 5. 查询
response = rag_chain.invoke("什么是LangChain?")
print(response)跑通了基础版RAG之后,你会发现实际效果不一定令人满意——未来还需要系统地解决这些问题。