数据向量化
#读取 现有json文件,不需要分割的数据直接构建
import json
from langchain_experimental.text_splitter import SemanticChunker
from langchain_community.vectorstores import FAISS
from langchain_core.documents import Document
# 读取文件内容
with open("./iciba_data_multi.json", encoding="utf-8") as f:
json_data = json.load(f)
# 加载embedding模型
from langchain_huggingface import HuggingFaceEmbeddings
MODEL_PATH = "/Users/t-mac/.cache/huggingface/hub/models--Qwen--Qwen3-Embedding-0.6B/snapshots/c54f2e6e80b2d7b7de06f51cec4959f6b3e03418"
# mps mac芯片mps加速
embeddings = HuggingFaceEmbeddings(
model_name=MODEL_PATH,
model_kwargs={"device": "mps"},
encode_kwargs={"normalize_embeddings": True}
)
# 2. 准备文档列表
# 这里我们不再使用 text_splitter,而是手动构建 Document 列表
documents = []
for item in json_data:
# 拼接文本:英文+中文
full_text = f"{item['content']} {item['note']}"
# 构建 LangChain 的 Document 对象
# page_content 是要向量化的内容
# metadata 是你想保留但不参与向量化的信息(比如日期)
doc = Document(
page_content=full_text,
metadata={"date": item["date"]}
)
documents.append(doc)
# 从文档列表创建 FAISS 向量库
vector_store = FAISS.from_documents(documents=documents, embedding=embeddings)
# 【可选】持久化存储:将索引保存到本地磁盘
vector_store.save_local("faiss_index")
Ollama 运行 Qwen3.5-2B
❯ ollama run qwen3.5:2b
pulling manifest
pulling b709d81508a0: 100% ▕██████████████████████████████████████▏ 2.7 GB
pulling 9be69ef46306: 100% ▕██████████████████████████████████████▏ 11 KB
pulling 9371364b27a5: 100% ▕██████████████████████████████████████▏ 65 B
pulling ee043a99abe5: 100% ▕██████████████████████████████████████▏ 473 B
verifying sha256 digest
writing manifest
success
>>>
线阶段:RAG 问答
# 在线阶段:RAG 问答
# 1. 核心思路
# 创建一个 “检索工具”,AI 回答问题前,先调用这个工具找相关文档,再结合文档回答(避免瞎编)。
import json
from langchain.agents import create_agent
from langchain_core.tools import tool
from langchain_ollama import ChatOllama
# ==========================================
# 1. 初始化模型
# ==========================================
model = ChatOllama(
model="qwen3.5:2b",
base_url="http://localhost:11434",
temperature=0.7,
)
# ==========================================
# 2. 模拟你的知识库数据 (实际使用时请替换为你的向量库检索逻辑)
# ==========================================
# 这里为了演示,我直接把你的 JSON 数据放在这里,实际应替换为 vector_store.similarity_search(query)
@tool
def search_docs(query: str) -> str:
"""
在文档库中搜索相关信息。
如果用户询问关于日期、格言或特定事件的内容,请使用此工具。
"""
# --- 实际逻辑替换结束 ---
formatted_results = []
results = ensemble_retriever.invoke(query)
for doc in results:
text = f"内容: {doc.page_content}"
formatted_results.append(text)
return "\n---\n".join(formatted_results)
# ==========================================
# 3. 创建 AI Agent
# ==========================================
agent = create_agent(
model=model,
tools=[search_docs],
system_prompt="""你是每日一词的助手。
1. 回答用户问题前,必须先调用 search_docs 工具查找信息。
2. 只能根据搜索到的 [内容] 和 [备注] 进行回答。
3. 如果搜索不到相关信息,请直接说“我在日记中没找到相关内容”,不要编造。
4. 回答时直接输出工具查询的内容。
"""
)
# ==========================================
# 4. 问答循环
# ==========================================
print("🤖 助手已就绪,请问关于这些日期的格言,你想知道什么?")
while True:
try:
query = input("\n请输入你的问题 (输入 q 退出): ")
if query.lower() == 'q':
break
# 调用 Agent
# 注意:这里使用 invoke 传入字典
response = agent.invoke({
"messages": [{"role": "user", "content": query}]
})
# 【关键优化】:正确提取回复内容
# response["messages"] 是一个列表,[-1] 是最后一条消息对象
# .content 是获取该对象中的文本内容
final_answer = response["messages"][-1].content
print("\n📝 助手回答:")
print(final_answer)
print("-" * 30)
except Exception as e:
print(f"发生错误: {e}")
结果
