from langchain_experimental.llms.ollama_functions import OllamaFunctions
from langchain_core.messages import HumanMessage
from langchain_core.messages import AIMessage
from langchain_community.tools.ddg_search.tool import DuckDuckGoSearchRun
import json
search = DuckDuckGoSearchRun()
model = OllamaFunctions(model="mistral:7b-instruct-v0.3-q5_K_M", format="json")
model2 = OllamaFunctions(model="mistral:7b-instruct-v0.3-q5_K_M", format="json")
model = model.bind(
functions=[
{
"name": "get_current_weather",
"description": "Get the current weather in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city and state, " "e.g. San Francisco, CA",
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
},
},
"required": ["location"],
},
}
]
)
# 使用 JsonOutputToolsParser 来试图解析结果
# https://python.langchain.com/docs/modules/model_io/chat/function_calling#binding-functions
# tool_chain = model | JsonOutputToolsParser(name="get_current_weather")
# result = tool_chain.invoke("what is the weather in Boston?")
# print(result)
# 这个方法是废的,因为这是针对OpenAI的
def get_current_weather(location):
res = "真的是在被call哦,get_current_weather:"+location
print(res)
result = search.run("what is the current weather in "+location)
print("==========================search的返回==================")
print(result)
return result
def chat(input):
result=model.invoke(input)
print("==========================模型的返回==================")
print(result)
print("==========================模型的返回==================")
cur_tool_calls = result.tool_calls
nums_of_tool_calls = len(cur_tool_calls)
if nums_of_tool_calls!=0:
# 判断字符串是否是可调用的函数
#https://stackoverflow.com/questions/59912800/how-do-i-check-if-a-string-is-a-callable-name-in-python
function_call_name = cur_tool_calls[0]['name']
function_call_arguments = cur_tool_calls[0]['args']
print(function_call_arguments)
if callable(globals()[function_call_name]):
print(f"{function_call_name} 是当前文件中可调用的函数。")
location = function_call_arguments["location"]
print("location:",location)
res = eval(function_call_name)(location)
result = model2.invoke(res+"\n\n 根据上下文,并且使用celsius作为单位,使用中文来总结,这个城市的天气是怎样的?")
print("==========================最终的结论==================")
print("\n")
print(result.content)
print("\n")
else:
print(f"{function_call_name} 不是当前文件中可调用的函数。")
return result
# 现在这个事情里有一个致命的缺陷就是,它一定以及肯定会启动一个tool call
# 这太二逼了只能说
chat_history = []
while True:
user_input = input("我:")
myNewMsg = HumanMessage(content=user_input)
chat_history.append(myNewMsg)
resp = chat(chat_history)
print("==============机器人的回复==================")
print(resp.content)
print("==============机器人的回复==================")
respAImsg = AIMessage(content=resp.content)
chat_history.append(respAImsg)
print(chat_history)
print(len(chat_history))
#https://python.langchain.com/v0.2/docs/tutorials/chatbot/
#然后看着这令人蛋疼的代码去一点点构建带history的对话机器人吧首先给出调用的代码,这里利用了之前调用豆包的服务器端的代码的技巧
lanchain写的哪个代码啊,又臭又长,十分抽象
https://github.com/lemonhall/RMMZ_GPT_movement/blob/main/server/main.py
其实llm能处理对话的本质就是那个数组而已
DEFAULT_SYSTEM_TEMPLATE = """You have access to the following tools:
{tools}
你可以选择以上的其中之一的工具来回答用户,但如果用户的query与所使用的工具描述无关,则不必call任何工具。
比如:用户向你问好,你当然也要回答你好啊,而别使用工具。
respond with only a JSON object matching the following schema:
{{
"tool": <name of the selected tool>,
"tool_input": <parameters for the selected tool, matching the tool's JSON schema>
}}
""" # noqa: E501
DEFAULT_SYSTEM_TEMPLATE_BAK = """You have access to the following tools:
{tools}
You must always select one of the above tools and respond with only a JSON object matching the following schema:
{{
"tool": <name of the selected tool>,
"tool_input": <parameters for the selected tool, matching the tool's JSON schema>
}}
""" # noqa: E501然后我发现了为什么OllamaFunctions如此霸道的原因了,就是它原来的提示词,强制让llm必须使用其中一个工具
这就让这个llm变成了纯纯的一个天气查询器了
我需要解决的,就是何时,以及要不要调用的一个文本分类问题,你倒好,直接给我强制调用了,搞得llm像个智障
修改之后对话会变得较为正常,但文本分类问题依旧存在



其实还是有点智障的
但起码可以同时聊天气和其它的话题并保持上下文
否则成了一个专用的天气查询工具有个屁用啊
所以langchain给的那些个例子,可以说就是没用的东西

所以这真的很糟糕
工具调用本质上需要一整套的文本分类去调教,这才是最可怕的地方