Skip to content

Ollama-python:定义工具集,增强大模型的能力

发表: at 11:00

Ollama 是一个优秀的本地部署与管理大模型的框架。通过 Ollama,我们可以在本地部署、定制自己的大模型服务。Ollama 支持使用流行的模型(如 Llama 3.1、qwen 2.5)进行工具调用。针对用户的问题提示(promt),大模型可判断是否使用工具并执行工具,根据工具的执行结果来回答用户的问题。设定一系列的工具集,可以增强大模型的能力,使大模型能够执行更复杂的任务,或与外部世界进行交互。

函数即工具

在 Ollama 中,可以将 Python 函数作为工具传递给大模型,从而让大模型在回答问题时调用这些工具。 Ollama-python 库通过 Pydantic,对函数文档进行解析,生成 JSON Schema。函数的 JSON Schema 保存有以下信息:

以数学运算的加法为例,加法函数定义为(使用类型注解和 Google 风格的文档字符串来定义函数):

def add_two_numbers(a: float, b: float) -> float:
    """
    Add two numbers (including decimals)

    Args:
      a (float): The first number
      b (float): The second number

    Returns:
      float: The sum of the two numbers
    """
    return a + b

Ollama-python 会自动将上面的加法函数定义转为以下 JSON:

{
    "type":"function",
    "function":{
        "name":"add_two_numbers",
        "description":"Add two numbers (including decimals)",
        "parameters":{
            "type":"object",
            "required":[
                "a",
                "b"
            ],
            "properties":{
                "a":{
                    "type":"float",
                    "description":"The first number"
                },
                "b":{
                    "type":"float",
                    "description":"The second numberr"
                }
            }
        }
    }
}

我们可以将函数作为工具,传递给大模型,大模型在回答用户问题时,会判断是否要调用工具:

from ollama import Client
from ollama import ChatResponse

client = Client()
prompt = '10 加 4 等于多少?'
messages = [{'role': 'user', 'content': prompt}]

response: ChatResponse = client.chat(
    model='qwen2.5:7b',
    messages=messages,
    tools=[add_two_numbers]  # add_two_numbers 可以是一个函数,或是包含函数信息的 json
) 

数学运算应用

大模型在回答高位数字的数学运算时,一般给不出正确的答案。下面的示例,介绍如何通过调用工具,让大模型准确地回答高位数字运算相关的问题。

代码逻辑

  1. 定义工具函数:

    • 定义了四个基本的数学运算函数:加法、减法、乘法和除法。
    • 每个函数都带有类型注解和文档字符串。Ollama 可根据函数定义生成 JSON Schema。
    • 除了直接传递函数,还可以手动定义工具的 JSON Schema(如 subtract_two_numbers_tool)。
  2. 调用工具并处理响应:

    • 用户输入一个问题。
    • Ollama 模型根据问题决定是否调用工具。如果模型请求调用工具,代码会根据模型提供的参数调用相应的函数,并将结果反馈给模型。
    • 最终,模型根据工具的输出生成回答。
from ollama import Client
from ollama import ChatResponse

def add_two_numbers(a: float, b: float) -> float:
    """
    Add two numbers (including decimals)

    Args:
      a (float): The first number
      b (float): The second number

    Returns:
      float: The sum of the two numbers
    """
    return a + b

def multiply_two_numbers(a: float, b: float) -> float:
    """
    Multiply two numbers (including decimals)

    Args:
      a (float): The first number
      b (float): The second number

    Returns:
      float: The product of the two numbers
    """
    return a * b


def divide_two_numbers(a: float, b: float) -> float:
    """
    Divide one number by another (including decimals)

    Args:
      a (float): The numerator
      b (float): The denominator

    Returns:
      float: The quotient of a divided by b
    """
    if b == 0:
        raise ZeroDivisionError("Division by zero is not allowed.")
    return a / b


def subtract_two_numbers(a: float, b: float) -> float:
    """
    Subtract two numbers
    """
    return a - b

# Tools can still be manually defined and passed into chat
subtract_two_numbers_tool = {
    'type': 'function',
    'function': {
      'name': 'subtract_two_numbers',
      'description': 'Subtract two numbers',
      'parameters': {
        'type': 'object',
        'required': ['a', 'b'],
        'properties': {
          'a': {'type': 'float', 'description': 'The first number'},
          'b': {'type': 'float', 'description': 'The second number'},
        },
      },
    },
}

# 主函数:调用工具并处理模型的响应
def call_tools(prompt):
    client = Client()  # 创建 Ollama 客户端实例
    messages = [{'role': 'user', 'content': prompt}]  # 用户输入的消息

    # 定义可用的函数工具
    available_functions = {
        'add_two_numbers': add_two_numbers,
        'subtract_two_numbers': subtract_two_numbers,
        'multiply_two_numbers': multiply_two_numbers,
        'divide_two_numbers': divide_two_numbers
    }

    # 调用 Ollama 的 chat 方法,传递工具
    response: ChatResponse = client.chat(
        model='qwen2.5:7b',  # 使用的模型
        messages=messages,  # 用户输入的消息
        tools=[add_two_numbers, subtract_two_numbers_tool, multiply_two_numbers, divide_two_numbers]
    )

    # 如果模型请求调用工具
    if response.message.tool_calls:
        for tool in response.message.tool_calls:
            if function_to_call := available_functions.get(tool.function.name):  # 获取对应的函数
                print('调用函数:', tool.function.name)
                print('函数参数:', tool.function.arguments)
                output = function_to_call(**tool.function.arguments)  # 调用函数并获取输出
                print('函数输出:', output)
            else:
                print('找不到函数:', tool.function.name)
        messages.append(response.message)  # 将工具调用结果添加到消息中
        messages.append({'role': 'tool', 'content': str(output), 'name': tool.function.name})
        # 获取最终响应
        final_response = client.chat(model='qwen2.5:7b', messages=messages)
        print('AI 助手回答:', final_response.message.content)
    else:
        print('AI 助手判断不需要调用工具')
        final_response = client.chat(model='qwen2.5:7b', messages=messages)
        print('AI 助手回答:', final_response.message.content)

# 程序入口
if __name__ == '__main__':
    prompt = input("用户: ")  # 获取用户输入
    call_tools(prompt)  # 调用主函数

提问示例

尝试让 deepseek-r1 回答上述问题。deepseek-r1可以回答上面的问题,但需要深度思考 231 秒。基于工具+ qwen2.5:7b,即可以较快地回答上面的问题。

deepseek-r1

目前上架 Ollama 的 deepseek-r1 模型还不支持工具调用。笔者会关注 deepseek-r1 模型后续在 Ollama 上的更新情况。若 Ollama 上的 deepseek-r1 模型支持工具调用,模型推理能力加上工具集,相信大模型服务能完成更复杂的任务。

文章来源:微信公众号-数智脉动,原始发表时间:2025年02月17日。


上篇文章
一文说清楚让LangChain大佬“开战”的MCP是什么?
下篇文章
推荐 20 个热门 MCP Server,让 AI 工具更加强大