当前位置:   article > 正文

LLM大语言模型(十):LangChain自定义Agent使用自定义的LLM

LLM大语言模型(十):LangChain自定义Agent使用自定义的LLM

背景

独立部署ChatGLM3-6B并提供HTTP API能力。

自定义LLM封装对ChatGLM3-6B的访问。

创建一个简单的Agent来使用自定义的LLM。

自行封装LLM(MyChatGLM)

上一篇文章LLM大语言模型(九):LangChain封装自定义的LLM-CSDN博客

已经介绍过如何在LangChain里封装自定义的LLM。

本文对本地部署的ChatGLM3-6B进行了简单的封装。

  1. import requests
  2. import json
  3. from typing import Any, List, Optional
  4. from langchain.llms.base import LLM
  5. from langchain_core.callbacks import CallbackManagerForLLMRun
  6. class MyChatGLM(LLM):
  7. model: str = "chatglm3-6b"
  8. url: str = "http://localhost:8000/v1/chat/completions"
  9. # def __init__(self):
  10. # super().__init__()
  11. @property
  12. def _llm_type(self) -> str:
  13. return "MyChatGLM"
  14. def _resp_process_mock(self,input:str,resp:str):
  15. final_answer_json = {
  16. "action": "Final Answer",
  17. "action_input": input
  18. }
  19. return f"""
  20. Action:
  21. ```
  22. {json.dumps(final_answer_json, ensure_ascii=False)}
  23. ```"""
  24. def _call(self, prompt: str, stop: Optional[List[str]] = None, run_manager: Optional[CallbackManagerForLLMRun] = None, **kwargs: Any) -> str:
  25. data = {}
  26. data["model"] = self.model
  27. lst = []
  28. lst.append({"role":"user","content":prompt})
  29. data["messages"] = lst
  30. resp = self.doRequest(data)
  31. return self._resp_process_mock(prompt,resp)
  32. def doRequest(self,payload:dict) -> str:
  33. # 请求头
  34. headers = {"content-type":"application/json"}
  35. # json形式,参数用json
  36. res = requests.post(self.url,json=payload,headers=headers)
  37. return res.text
  38. mllm = MyChatGLM()
  39. print(mllm._llm_type)
  40. # mllm._llm_type = "haha" _llm_type该属性是无法被修改的
  41. print(mllm("hello world!"))

_call()方法的实现

本示例是个简单的QA,没有记录history。

_call()方法内部就是通过HTTP POST请求调用本地部署的ChatGLM3-6B服务。

_resp_process_mock()方法

这个是对LLM返回的结果进行了格式化的封装,直接返回action: Final Answer。

为什么这样返回,下文有解释。

自定义Agent

Agent使用的是LangChain的Structured chat类型的Agent,执行结构化的chat能力。

Structured chat类型的Agent支持多个Tool的输入,本文示例未考虑引入tool,所以在_resp_process_mock()里直接返回action: Final Answer。

action: Final Answer表示chat过程中使用tool的推理执行过程已经结束。(详见下文)

  1. from langchain import hub
  2. from langchain.agents import AgentExecutor, create_structured_chat_agent
  3. from langchain_community.tools.tavily_search import TavilySearchResults
  4. from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
  5. from my_chatglm3 import MyChatGLM
  6. if __name__ == "__main__":
  7. # tools = [TavilySearchResults(max_results=1)]
  8. tools = []
  9. prompt = hub.pull("hwchase17/structured-chat-agent")
  10. # Choose the LLM to use
  11. llm = MyChatGLM()
  12. # Construct the agent
  13. agent = create_structured_chat_agent(llm, tools, prompt)
  14. # Create an agent executor by passing in the agent and tools
  15. agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True, handle_parsing_errors=True)
  16. agent_executor.invoke({"input": "我心情不好,给我讲个笑话逗我开心"})

ChatPromptTemplate structured-chat-agent

使用的是hwchase17/structured-chat-agent,其结构如下:

  1. System: Respond to the human as helpfully and accurately as possible. You have access to the following tools:
  2. Use a json blob to specify a tool by providing an action key (tool name) and an action_input key (tool input).
  3. Valid \"action\" values: \"Final Answer\" or
  4. Provide only ONE action per $JSON_BLOB, as shown:
  5. ```\n{\n \"action\": $TOOL_NAME,\n \"action_input\": $INPUT\n}\n```
  6. Follow this format:
  7. Question: input question to answer
  8. Thought: consider previous and subsequent steps
  9. Action:
  10. ```
  11. $JSON_BLOB
  12. ```
  13. Observation: action result
  14. ... (repeat Thought/Action/Observation N times)
  15. Thought: I know what to respond
  16. Action:
  17. ```
  18. {
  19. \"action\": \"Final Answer\",
  20. \"action_input\": \"Final response to human\"
  21. }
  22. Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:```$JSON_BLOB```then Observation
  23. Human: 我心情不好,给我讲个笑话逗我开心
  24. (reminder to respond in a JSON blob no matter what)

第一段:声明System信息,类似我们使用LLM对话时的prompt engineering,指定角色等context信息。

第二段:声明如何使用tool以及推理过程,tool本文不涉及后续再写。注意对推理过程的约束,推理结束的标志是action: Final Answer,如果LLM给Agent返回的结果一直没有action: Final Answer,会导致Agent一直推理下去进入“死循环”。

这也是为什么_resp_process_mock()方法直接就返回action: Final Answer,一轮对话就结束就完事。

第三段:声明输出格式。

第四段:Human用户的输入

Agent执行结果

  1. > Entering new AgentExecutor chain...
  2. Action:
  3. ```
  4. {"action": "Final Answer",
  5. "action_input": "{\"model\":\"chatglm3-6b\",\"id\":\"\",\"object\":\"chat.completion\",\"choices\":[{\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"{\\n \\\"action\\\": \\\"Final Answer\\\",\\n \\\"action_input\\\": \\\"A joke for you: Why was the math book sad? Because it had too many problems.\\\"\\n}\",\"name\":null,\"function_call\":null},\"finish_reason\":\"stop\"}],\"created\":1712419428,\"usage\":{\"prompt_tokens\":297,\"total_tokens\":339,\"completion_tokens\":42}}"}
  6. ```
  7. > Finished chain.

可以看到这里的推理过程,只有一个action: Final Answer。

action_input这里直接返回了LLM的原始回答。

其中的A joke for you: Why don't scientists trust atoms? Because they make up everything! 这个就是LLM的回答。

 参考

  1. LLM大语言模型(九):LangChain封装自定义的LLM-CSDN博客
  2. LLM大语言模型(八):ChatGLM3-6B使用的tokenizer模型BAAI/bge-large-zh-v1.5-CSDN博客
  3. LLM大语言模型(七):部署ChatGLM3-6B并提供HTTP server能力
  4. LLM大语言模型(四):在ChatGLM3-6B中使用langchain_chatglm3-6b langchain-CSDN博客
  5. LLM大语言模型(一):ChatGLM3-6B本地部署-CSDN博客
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/383689
推荐阅读
相关标签
  

闽ICP备14008679号