langchain_agent的应用讲解以及demo-结合数据库记忆历史信息

之前了解到最原始的func_calling,调用方便带定义复杂 在langchain中,集成了很多方法例如tavily的搜索

1,使用tool

from langchain_community.tools.tavily_search import TavilySearchResults
search =  TavilySearchResults(
    api_key=os.getenv("TAVILY_API_KEY"),
)

这就是一个集成的tool

那么自定义tool呢

from langchain.tools import Tool
toolResult = Tool.from_function(
    func=get_retrieval_result,
    name="searchAgent",
    description="这个工具只用来测试,除了用户问到开发商相关问题否则不要用这个工具",
    args={"query": "输入的问题"}
)

还有一种方案就是def方法上加@tool注解,根据自己爱好使用

2.创建使用agent

为什么要使用agent呢? 我们知道 在之前的原生方法中我们调用tool的方法是很呆的,每次判断大模型的返回值func-calling中有没有需要调用的tool  然后if_else去执行这个方法,想下面这样

while message.tool_calls and message.tool_calls[0].function is not None:

    name = message.tool_calls[0].function.name
    print(name)
    if name == "sum":
        arguments = json.loads(message.tool_calls[0].function.arguments)["query"]
        sumReturn =  sum(arguments)
        messages.append(message)
        messages.append({
            'tool_call_id': message.tool_calls[0].id,
            'role': 'tool',
            'name': name,
            'content': str(sumReturn)
        })
    elif name == "selXM":
        sumReturn = "20"
        messages.append(message)
        messages.append({
            'tool_call_id': message.tool_calls[0].id,
            'role': 'tool',
            'name': name,
            'content': str(sumReturn)
        })
    response = call_model_with_tool_response(messages)
    message = response.choices[0].message
    print(message.content)

可以看到这样代码的可扩展性非常滴而且代码很呆  当然大家可以根据自己封装的方法 或者根据反射来解决这个问题  这样解决起来总会很麻烦  agent提供了自动化调用的一个流程

初始化一个agent

from langchain.agents import AgentType, initialize_agent
agent = initialize_agent(tools,langchainModel, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,memory=memory, verbose=True)

其中tools就是我们上文中提到的tools  langchainmodel是我们的llm大语言模型 agent=  后面是agent的模式,向零样本啊  自问自答这些,用来改变agent的思 memory则是大模型的记忆

最后agent.invoke()调用大模型,大模型会根据你的提示信息以及工具的描述信息自己调用工具中的方法并给你返回值信息

3,demo-结合数据库记忆历史信息

1首先这个是根据memory进行记忆的代码我研究了很久所以拿出来讲一下

import os

from langchain.memory import ConversationBufferMemory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_openai import ChatOpenAI
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.tools.tavily_search import TavilySearchResults
from dotenv import load_dotenv
from langchain.vectorstores.chroma import Chroma
# 加载环境变量
load_dotenv()
search =  TavilySearchResults(
    api_key=os.getenv("TAVILY_API_KEY"),
)
print(search.invoke("python"))
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
pdfLoader = PyPDFLoader("../LangChain/异地测试安排 20230424.pdf")
documents =  pdfLoader.load_and_split()
# for  doc in documents:
#     print(doc.page_content+"===============")#打印出来是一条document
testSplit = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=30)
splitText = testSplit.split_text(documents[0].page_content)
embeddings = DashScopeEmbeddings(
    model="text-embedding-v3",  # 阿里云支持的模型
    dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"),
)
#通过向量检索  如果要使用检索器切片必须是document格式
# retriever = Chroma.from_texts(splitText, embeddings)
# print(len(splitText))
# print(retriever.similarity_search("银海HIS", k=1))
splitText1 = testSplit.create_documents([documents[0].page_content])
retriever = Chroma.from_documents(splitText1, embeddings).as_retriever(search_kwargs={"k": 2})
def  get_retrieval_result(query):
    result = retriever.invoke(query)
    return result
print(get_retrieval_result("银海HIS"))

from langchain.agents import AgentType, initialize_agent
from langchain.tools.retriever import create_retriever_tool
from langchain.tools import Tool
from langchain_core.messages import SystemMessage, AIMessage, HumanMessage
searchAgent = create_retriever_tool(retriever,"searchAgent","搜索开发商信息,如果使用开发商信息请使用此工具")
toolResult = Tool.from_function(
    func=get_retrieval_result,
    name="searchAgent",
    description="这个工具只用来测试,除了用户问到开发商相关问题否则不要用这个工具",
    args={"query": "输入的问题"}
)
tools = [search, toolResult]
from langchain.prompts import PromptTemplate
# promptTemplate = "根据参考资料回答问题:{question} 参考资料:{chat_history}"
# prompt = PromptTemplate.from_template(promptTemplate)
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一个专业助手,会记住用户的对话历史。如果用户指定了你的名字,你需要在后续对话中使用它。"),
    MessagesPlaceholder(variable_name="chat_history"),
    ("human", "{input}"),
])
langchainModel = ChatOpenAI(
    model="qwen-plus",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True
)
agent = initialize_agent(tools,langchainModel, agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,memory=memory,prompt = prompt,verbose=True,handle_parsing_errors=True)

def get_response(question):
    global chatHistory
    response = agent.invoke({"input":question})
    return response

questions = ["我的名字是刘老师","我的名字是什么"]
for question in questions:
    print(get_response(question))

首先我的步骤和上面一样,去加载,但是在加载记忆的时候出现了问题

仔细检查原因发现之前使用的是  agentType = ZERO_SHOT_REACT_DESCRIPTION  这个模型没有记忆能力,所以大家使用agent一定要先了解一下agentType啊(哭)

2因为时间紧,所以新开了一个方法使用向量存储,都是简单的代码,主要是看实现方式

import os

from langchain_core.documents import Document
from langchain_openai import ChatOpenAI
from langchain_community.embeddings import DashScopeEmbeddings
from langchain_community.tools.tavily_search import TavilySearchResults
from dotenv import load_dotenv
from langchain.vectorstores.chroma import Chroma
from langchain.memory import ConversationBufferMemory  # 【新增】导入对话记忆组件


load_dotenv()
search = TavilySearchResults(api_key=os.getenv("TAVILY_API_KEY"))
print(search.invoke("python"))

from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter

pdfLoader = PyPDFLoader("../LangChain/异地测试安排 20230424.pdf")
documents = pdfLoader.load_and_split()

testSplit = RecursiveCharacterTextSplitter(chunk_size=200, chunk_overlap=30)
splitText1 = testSplit.create_documents([documents[0].page_content])

embeddings = DashScopeEmbeddings(
    model="text-embedding-v3",
    dashscope_api_key=os.getenv("DASHSCOPE_API_KEY"),
)

retriever = Chroma.from_documents(splitText1, embeddings).as_retriever(search_kwargs={"k": 2})

def get_retrieval_result(query):
    result = retriever.invoke(query)
    return result

print(get_retrieval_result("银海HIS"))

from langchain.agents import AgentType, initialize_agent
from langchain.tools.retriever import create_retriever_tool
from langchain.tools import Tool
from langchain_core.messages import SystemMessage, AIMessage, HumanMessage

searchAgent = create_retriever_tool(retriever, "searchAgent", "搜索开发商信息,如果使用开发商信息请使用此工具")

toolResult = Tool.from_function(
    func=get_retrieval_result,
    name="searchAgent",
    description="搜索开发商信息,如果使用开发商信息请使用此工具",
    args={"query": "输入的问题"}
)

tools = [search, toolResult]

from langchain.prompts import PromptTemplate

promptTemplate = "请回答问题:{input} 参考资料{chat_history}"
prompt = PromptTemplate.from_template(promptTemplate)

langchainModel = ChatOpenAI(
    model="qwen-plus",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# 【新增】创建对话记忆组件
memory = ConversationBufferMemory(memory_key="chat_history", return_messages=True)

# 【修改】传递 memory 组件给 Agent,让它记住对话历史
agent = initialize_agent(
    tools,
    langchainModel,
    agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
    verbose=True,
    memory=memory
)
#初始化数据库
persist_directory = "./chroma_db"
vectorstore = Chroma(persist_directory=persist_directory, embedding_function=embeddings)
retriever1 = vectorstore.as_retriever(search_kwargs={"k": 2})
# 【修改】去掉 chatHistory,改用 memory 组件
def get_response(question):
    global  retriever1
    global  vectorstore
    resp =  retriever1.invoke(question)
    response = agent.invoke(prompt.format(input=question, chat_history=str(resp)))  # 不再使用手动维护的 chatHistory
    documents1 = [
        Document(page_content=response["input"], metadata={"source": "agent_input"}),
        Document(page_content=response["output"], metadata={"source": "agent_output"}),
    ]
    vectorstore.add_documents(documents1)
    return response

questions = ["我的名字是刘老师", "你是当当的小红帽", "我的名字是什么"]
for question in questions:
    print(get_response(question))

代码运行正常

你可能感兴趣的:(langchain)