探索 LangChain 与 Ollama 实现函数调用:以获取天气信息为例

245 阅读4分钟

一、引言

在人工智能与自然语言处理的快速发展中,我们经常需要借助大语言模型完成复杂的任务。LangChain 作为一个强大的开发框架,为我们提供了便捷的工具来构建基于语言模型的应用。而 Ollama 则是一个可以轻松运行各种语言模型的平台。本文将结合 LangChain 和 Ollama,详细介绍如何利用函数调用功能来获取特定城市的天气信息,帮助你更好地理解和运用这两个工具。

二、环境准备

在开始之前,我们需要确保已经安装了必要的库。可以使用以下命令进行安装: bash pip install langchain Ollama pydantic 同时,要确保 Ollama 服务已经在本地 http://localhost:11434 启动,并且加载了 deepseek - r1:1.5b 模型。

三、代码实现

3.1 定义函数模型

我们首先定义一个 GetWeather 类,它继承自 pydantic 的 BaseModel,用于描述获取天气信息函数的参数和实现。

from pydantic import BaseModel, Field
import json

class GetWeather(BaseModel):
    city: str = Field(description="城市")

    def run(self):
        weather_info = {
            "city": self.city,
            "temperature": "25°C",
            "condition": "Sunny"
        }
        return json.dumps(weather_info)

这里,city 是函数的参数,代表要查询天气的城市。run 方法模拟了获取天气信息的过程,返回一个包含城市、温度和天气状况的 JSON 字符串。

3.2 封装函数调用类

接下来,我们创建一个 LceFunctionCall 类,用于封装函数调用的逻辑。

from langchain.chat_models import ChatOllama
from langchain.utils.openai_functions import convert_pydantic_to_openai_function
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough

class LceFunctionCall(object):
    def __init__(self, model, base_url):
        self.__chat = ChatOllama(model=model, base_url=base_url, streaming=True)

    def invoke(self, city):
        prompt = ChatPromptTemplate.from_messages([
            SystemMessage(content="你是一个聪明的助手,能根据用户需求调用合适的函数"),
            HumanMessage(content="请调用 GetWeather 函数来获取{city}的天气信息")
        ])
        function_schema = convert_pydantic_to_openai_function(GetWeather)

        def add_functions_to_model(messages):
            return self.__chat.invoke(messages, functions=[function_schema])

        chain = (
                {
                    "city": RunnablePassthrough()
                }
                | prompt
                | add_functions_to_model
                | StrOutputParser()
        )
        for chunk in chain.stream({"city": city}):
            if chunk:
                full_response = ""
                full_response += chunk
                print(chunk, end="", flush=True)
                try:
                    function_call = json.loads(full_response)
                    if "name" in function_call and function_call["name"] == "GetWeather":
                        params = function_call["parameters"]
                        weather = GetWeather(**params).run()
                        print(f"\n天气信息: {weather}")
                        full_response = ""  # 解析成功后清空响应
                except json.JSONDecodeError:
                    continue
  • __init__ 方法:初始化 ChatOllama 模型,设置模型名称和服务地址,并开启流式输出。

  • invoke 方法

    • 构建提示模板:使用 ChatPromptTemplate 构建包含系统消息和用户消息的提示模板,引导模型调用 GetWeather 函数。
    • 转换函数模式:使用 convert_pydantic_to_openai_function 将 GetWeather 类转换为 OpenAI 函数模式。
    • 定义链式调用:通过 RunnablePassthrough 和管道操作符 | 定义一个链式调用,将输入的城市信息传递给提示模板,再调用模型并解析输出。
    • 流式处理响应:使用 chain.stream 方法获取模型的流式输出,逐块处理并尝试解析为函数调用信息。如果解析成功且函数名为 GetWeather,则调用 GetWeather 类的 run 方法获取天气信息并输出。

3.3 主程序调用

最后,在主程序中创建 LceFunctionCall 类的实例,并调用 invoke 方法获取深圳的天气信息。

if __name__ == "__main__":
    lcel = LceFunctionCall(model="deepseek-r1:1.5b", base_url="http://localhost:11434")
    lcel.invoke(city="深圳")

提示:由于deepseek-r1:1.5b不支持函数调用,可以通过Agent方式实现,或者使用OpenAI提供的模型

四、代码解释

4.1 函数调用机制

通过 LangChain 的 convert_pydantic_to_openai_function 方法,我们将 GetWeather 类转换为模型可以理解的函数模式。在调用模型时,将函数模式作为参数传递给模型,模型会根据提示信息判断是否需要调用该函数。

4.2 流式输出处理

使用 ChatOllama 的流式输出功能,我们可以逐块获取模型的响应,提高用户体验。在处理流式输出时,我们需要将每一块内容拼接成完整的响应,并尝试解析为 JSON 格式。如果解析成功且包含函数调用信息,则调用相应的函数并输出结果。

五、注意事项

  • 模型支持:目前 deepseek - r1:1.5b 模型对函数调用的支持情况可能有限,你可能需要根据实际情况调整模型或提示信息。
  • 错误处理:在实际应用中,需要对函数调用和 JSON 解析过程中的错误进行更完善的处理,以确保程序的稳定性。

六、总结

通过本文的介绍,你学会了如何使用 LangChain 和 Ollama 实现函数调用,获取特定城市的天气信息。这种方法可以扩展到其他领域,如调用数据库查询、调用 API 接口等。希望本文能帮助你更好地利用 LangChain 和 Ollama 构建强大的语言模型应用。 以上就是关于利用 LangChain 和 Ollama 实现函数调用的详细介绍,赶紧动手试试吧! 你可以根据实际情况对文章内容进行调整和修改,或者提出更多的修改建议。