from langchain_community.vectorstores import FAISS from langchain_huggingface import HuggingFaceEmbeddings from langchain_core.documents import Document from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate from langchain_community.llms import HuggingFacePipeline import torch from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline # ========== 1. 加载嵌入模型 ========== embeddings = HuggingFaceEmbeddings( model_name=r"C:\Users\Lenovo\rag_scrapydb\src\local_embeddings_cache\all-MiniLM-L6-v2" ) # ========== 2. 加载 FAISS 向量库 ========== VECTOR_STORE_PATH = r"C:\Users\Lenovo\rag_scrapydb\src\my_vectorstore" vectorstore = FAISS.load_local(VECTOR_STORE_PATH, embeddings=embeddings, allow_dangerous_deserialization=True) retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索 top-3 文档 # ========== 3. 加载本地 LLM(以 ChatGLM 为例)========== model_name = "chatglm-6b" # 替换为你自己的本地模型路径 tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True).half().cuda() pipe = pipeline( "text-generation", model=model, tokenizer=tokenizer, max_new_tokens=200, device=0, ) llm = HuggingFacePipeline(pipeline=pipe) # ========== 4. 定义 Prompt Template ========== prompt_template = """请基于以下提供的背景信息,回答用户的问题。如果无法找到相关信息,请说明原因。 背景信息: {context} 问题: {question} 请确保回答简洁清晰,并在回答末尾列出引用来源(网址)。 """ PROMPT = PromptTemplate( template=prompt_template, input_variables=["context", "question"] ) # ========== 5. 创建 RAG Chain ========== qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=retriever, chain_type_kwargs={"prompt": PROMPT} ) # ========== 6. 连续对话能力支持(维护历史)========== def chat(): history = [] while True: user_input = input("你:") if user_input.lower() in ['退出', 'exit', 'q']: break # 将历史拼接到当前问题中 full_question = "\n".join([f"用户:{h[0]}\n助手:{h[1]}" for h in history]) + f"\n用户:{user_input}" result = qa_chain.invoke({"query": full_question}) answer = result["result"] # 提取引用链接 docs = vectorstore.similarity_search(user_input, k=3) sources = set(doc.metadata.get('source', '') for doc in docs if doc.metadata.get('source')) source_str = "\n".join([f"[{i+1}] {s}" for i, s in enumerate(sources)]) print(f"助手:{answer}\n\n参考链接:\n{source_str}") # 记录对话历史 history.append((user_input, answer)) if len(history) > 5: # 控制历史长度防止过长 history.pop(0) if __name__ == "__main__": chat()改吧
时间: 2025-08-31 12:19:05 AIGC 浏览: 20
你给出的这段代码是一个完整的 **RAG(Retrieval-Augmented Generation)问答系统**,使用了:
- 本地 embedding 模型:`all-MiniLM-L6-v2`
- FAISS 向量数据库
- 本地 LLM:ChatGLM-6B
- LangChain 构建检索问答链
- 支持连续对话历史
---
## ✅ 当前代码存在的问题和改进建议
### ❗问题1:LLM 加载路径错误
```python
model_name = "chatglm-6b"
```
这行代码有问题!如果你没有设置模型缓存目录或 `chatglm-6b` 不在当前路径下,会报错。应该指定完整路径,例如:
```python
model_path = r"C:\models\chatglm-6b"
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).half().cuda()
```
---
### ❗问题2:未正确启用 `trust_remote_code`
虽然你设置了 `trust_remote_code=True`,但在某些版本中仍需手动确认是否允许远程执行代码。建议明确说明用途。
---
### ❗问题3:连续对话逻辑可以优化
目前你将历史拼接到 `full_question` 中传入 QA Chain,但 `RetrievalQA` 只处理 `query` 字段,并不会自动理解上下文历史。更好的方式是:
- 在 Prompt Template 中加入历史字段
- 使用支持记忆的 Chain,如 `ConversationalRetrievalChain`
---
## ✅ 改进后的完整代码如下:
```python
from langchain_community.vectorstores import FAISS
from langchain_huggingface import HuggingFaceEmbeddings
from langchain_core.documents import Document
from langchain.chains import ConversationalRetrievalChain
from langchain.prompts import PromptTemplate
from langchain_community.llms import HuggingFacePipeline
import torch
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
from langchain.memory import ConversationBufferMemory
# ========== 1. 加载嵌入模型 ==========
embeddings = HuggingFaceEmbeddings(
model_name=r"C:\Users\Lenovo\rag_scrapydb\src\local_embeddings_cache\all-MiniLM-L6-v2"
)
# ========== 2. 加载 FAISS 向量库 ==========
VECTOR_STORE_PATH = r"C:\Users\Lenovo\rag_scrapydb\src\my_vectorstore"
vectorstore = FAISS.load_local(VECTOR_STORE_PATH, embeddings=embeddings, allow_dangerous_deserialization=True)
retriever = vectorstore.as_retriever(search_kwargs={"k": 3}) # 检索 top-3 文档
# ========== 3. 加载本地 LLM(以 ChatGLM 为例)==========
model_path = r"C:\models\chatglm-6b" # 修改为你自己的模型路径
tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True)
model = AutoModelForCausalLM.from_pretrained(model_path, trust_remote_code=True).half().cuda()
pipe = pipeline(
"text-generation",
model=model,
tokenizer=tokenizer,
max_new_tokens=200,
device=0,
pad_token_id=tokenizer.eos_token_id # 避免警告
)
llm = HuggingFacePipeline(pipeline=pipe)
# ========== 4. 定义 Prompt Template ==========
prompt_template = """请基于以下提供的背景信息,回答用户的问题。如果无法找到相关信息,请说明原因。
历史对话:
{chat_history}
背景信息:
{context}
问题:
{question}
请确保回答简洁清晰,并在回答末尾列出引用来源(网址)。
"""
PROMPT = PromptTemplate(
template=prompt_template,
input_variables=["context", "question", "chat_history"]
)
# ========== 5. 创建带记忆的 RAG Chain ==========
memory = ConversationBufferMemory(memory_key="chat_history", input_key="question")
qa_chain = ConversationalRetrievalChain.from_llm(
llm=llm,
retriever=retriever,
combine_docs_chain_kwargs={"prompt": PROMPT},
memory=memory
)
# ========== 6. 运行聊天交互 ==========
def chat():
print("开始与 RAG 系统对话吧!输入 '退出' 结束程序。")
while True:
user_input = input("你:")
if user_input.lower() in ['退出', 'exit', 'q']:
break
result = qa_chain.invoke({"question": user_input})
answer = result["answer"]
# 提取引用链接
sources = set(doc.metadata.get('source', '') for doc in result["source_documents"] if doc.metadata.get('source'))
source_str = "\n".join([f"[{i+1}] {s}" for i, s in enumerate(sources)])
print(f"助手:{answer}\n\n参考链接:\n{source_str}")
if __name__ == "__main__":
chat()
```
---
## 🧠 改进点说明
| 原功能 | 改进后 |
|--------|--------|
| `RetrievalQA` | `ConversationalRetrievalChain`,原生支持对话历史 |
| 手动拼接 history | 使用 `ConversationBufferMemory` 自动管理对话历史 |
| Prompt 不包含 history | 新增 `{chat_history}` 变量到模板中 |
| LLM 路径不明确 | 明确使用本地模型路径加载 |
---
## ✅ 总结
你现在拥有了一个更稳定、更专业的 RAG 系统,具备以下能力:
- 使用本地 Embedding 模型进行向量化
- 使用 FAISS 存储文档向量
- 使用本地 LLM(ChatGLM-6B)生成答案
- 支持多轮对话上下文理解
- 可扩展性强,适合部署为本地服务
---
###
阅读全文
相关推荐















