利用LangGraph和LangChain构建基于本地知识库的Agent
前言
由于本人最近迷上了利用langchain和langgraph构建一个论文总结的智能体。于是想着记录一下整个构建过程。总体而言,构建过程和代码都比较简单。主要包含三个.py文件,分别是本地持久化向量库(避免每次都重新运行向量库),工具包和主程序。
目前代码已经在Github上开源。开源链接:Github链接。
麻烦各位点个Star。QWQ阿里嘎多。
Requirements
- Langchain;
- Langgraph ;
- langchain_community ;
- tqdm ;
- os;
- gradio;
- git
技术路线
采用的方法还是以增强检索(RAG)的方式来对本地的知识库进行检索。其流程图大致如下:
Vector_Persist文件
直接贴代码吧,不清楚的可以私信问我。
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from tqdm import tqdm
import os
# 获取文件路径函数
def get_files(dir_path):
file_list = []
for filepath, _, filenames in os.walk(dir_path):
for filename in filenames:
if filename.endswith(".pdf"):
file_list.append(os.path.join(filepath, filename))
return file_list
def get_text(dir_path):
file_lst = get_files(dir_path)
docs = []
for one_file in tqdm(file_lst):
file_type = one_file.split('.')[-1]
print(file_type)
if file_type == 'pdf':
loader = PyPDFLoader(one_file)
else:
# 如果是不符合条件的文件,直接跳过
continue
docs.extend(loader.load())
return docs
# 目标文件夹
tar_dir = ["./paper_pdf/",]
# 加载目标文件
docs = []
for dir_path in tar_dir:
docs.extend(get_text(dir_path))
# 对文本进行分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=20)
split_docs = text_splitter.split_documents(docs)
# 加载开源词向量模型
embeddings = HuggingFaceEmbeddings(model_name='./embeddings/bge-m3')
# 构建向量数据库
# 定义持久化路径
persist_directory = 'data_base/vector_db/chroma'
# 加载数据库
vectordb = Chroma.from_documents(
documents=split_docs,
embedding=embeddings,
persist_directory=persist_directory
)
# 将加载的向量数据库持久化到磁盘上
vectordb.persist()
print("finish!")
Tools文件
from langchain.agents import tool
from langchain_community.utilities import SerpAPIWrapper
from langchain_community.vectorstores import Chroma
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
#定义tools
#搜索工具
@tool
def search_sepapi(query:str):
"""
只有当需要了解实时信息或者不知道的事情的时候才会使用这个工具。
"""
serp = SerpAPIWrapper()
result = serp.run(query=query)
print("搜索结果:",result)
return result
#文档增强检索
@tool
def from_pdf_search(query:str):
"""
当提到使用本地知识库和总结论文的时候,必须用这个工具。
"""
persist_directory = './data_base/vector_db/chroma'
embedding = HuggingFaceEmbeddings(model_name='./embeddings/bge-m3')
print("加载数据库")
vector_db = Chroma(persist_directory=persist_directory,embedding_function=embedding)
retriever=vector_db.as_retriever()
result = retriever.get_relevant_documents(query)
return result
Agent文件
这里我调用了LangSmith来监控我的智能体每次用了多少token以及一些bug,如果不用LangSmith可以删掉前三个环境配置。
import os
#加载LangSmith,这里我调用了LangSmith来监控我的智能体每次用了多少token以及一些bug,如果不用LangSmith可以删掉前三个环境配置。
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = ""
os.environ["LANGCHAIN_PROJECT"] = ""
#加载SERP,一个用于联网的API
os.environ["SERPAPI_API_KEY"] = "你的SERP_API的APIKEY"
#加载自定义工具
from Mytools import *
from langchain_ollama import ChatOllama
from langchain.prompts import ChatPromptTemplate
from langgraph.prebuilt import create_react_agent
from langgraph.checkpoint.memory import MemorySaver
from langchain_openai import ChatOpenAI
SYSTEM_PROMPT="""
输入你的角色设定
"""
model="你的模型,例如gpt-3.5-turbo"
api_key="你的模型的apikey"
base_url="你购买的模型提供的url"
def load_chain():
llm = ChatOpenAI(model=model,api_key=api_key, base_url=base_url)
#llm = ChatOpenAI(model="gpt-3.5-turbo",api_key="sk-ksPmqN3bzyP8p1aQgUJnucSxsE8g8Ox6xwaBnJyJJeiSMtfK", base_url="https://chatapi.littlewheat.com/v1")
checkpointer = MemorySaver()
prompt = ChatPromptTemplate.from_messages([
("system",SYSTEM_PROMPT),
("placeholder","{messages}")
])
tools = [search_sepapi,from_pdf_search]
llm_with_tools = llm.bind_tools(tools)
agent = create_react_agent(model=llm_with_tools,tools=tools,prompt=prompt,checkpointer=checkpointer)
return agent
main文件
from agent import load_chain
import gradio as gr
from Mytools import *
SYSTEM_PROMPT="""
"""
agent = load_chain()
def agent_answer(question: str, history):
print(question)
if question == None or len(question) < 1:
return ""
try:
response = agent.invoke({"messages": [("user",question)]},
config={"configurable": {"thread_id": 42}})
return response["messages"][-1].content
except Exception as e:
return e
demo = gr.ChatInterface(
fn=agent_answer,
type="messages",
title="本地科研助理",
description="<center>基于GPT</center>"
)
demo.launch()
以上就是全部的代码内容。如果想要直接获得工程可以打开Github链接进行下载:https://github.com/crazyjack44/science_agent
在运行Github代码前,请先下载embedding模型。embedding模型由于太大,就没有直接放在github上了。
例如,采用bge-m3作为embedding,先去模搭社区(modelscope)上下载bge-m3
,下载在embedding文件下。
可以使用git的方式来下载:
git clone https://www.modelscope.cn/BAAI/bge-m3.git
下载完成后,先将你的pdf文件放入到paper_pdf
文件夹中,然后运行vector_persist.py
文件,运行结束后,就可以在agent.py
文件中填入你的模型名,api_key,system_prompt,最后运行main.py文件,就可以运行啦!
总的来说,代码量不多,构建的agent也较为简单,之后打算构建多智能体以及利用TTS加上声音,构建一个虚拟数字人