文档

代理流程

`.act()` 调用

如何使用 .act() 调用将大型语言模型 (LLM) 转换为可以在本地机器上执行任务的自主代理。

自动工具调用

我们引入了执行“回合”的概念,来描述运行工具、将其输出提供给 LLM,然后等待 LLM 决定下一步该做什么的组合过程。

执行回合

 • run a tool →
 ↑   • provide the result to the LLM →
 │       • wait for the LLM to generate a response

 └────────────────────────────────────────┘ └➔ (return)

模型可能会选择多次运行工具,然后才返回最终结果。例如,如果 LLM 正在编写代码,它可能会选择编译或运行程序,修复错误,然后再次运行,反复执行直到获得所需的结果。

考虑到这一点,我们说 .act() API 是一个自动的“多回合”工具调用 API。

快速示例

import lmstudio as lms

def multiply(a: float, b: float) → float:
    """Given two numbers a and b. Returns the product of them."""
    return a * b

model = lms.llm("qwen2.5-7b-instruct")
model.act(
  "What is the result of 12345 multiplied by 54321?",
  [multiply],
  on_message=print,
)

LLM “使用工具”意味着什么?

LLM 大多是文本输入、文本输出的程序。所以,您可能会问“LLM 如何使用工具?”答案是,一些 LLM 经过训练,会要求人类为它们调用工具,并期望工具输出以某种格式返回。

想象一下您正在通过电话为某人提供计算机支持。您可能会说“为我运行此命令...好,输出是什么?...好,现在点击那里告诉我它显示了什么...”。在这种情况下,您就是 LLM!您正在通过电话另一端的人间接“调用工具”。

并行运行多个工具调用

默认情况下,Python SDK 1.4.0 及更高版本将只在同一时间运行一个工具调用请求,即使模型在一个响应消息中请求了多个工具调用。这确保了即使工具实现不支持多个并发调用,请求也能正确处理。

当已知工具实现是线程安全的,并且既慢又频繁到值得并行运行时,max_parallel_tool_calls 选项指定将从单个模型响应中并行处理的最大工具调用请求数。此值默认为 1(等待每个工具调用完成后再开始下一个)。将此值设置为 None 将自动将并行工具调用的最大数量扩展为进程可用 CPU 核心数量的倍数。

重要提示:模型选择

用于工具使用的模型将极大地影响性能。

选择模型时的一些一般指导

  • 并非所有模型都能够智能地使用工具
  • 越大越好(即,7B 参数模型通常会比 3B 参数模型表现更好)
  • 我们观察到 Qwen2.5-7B-Instruct 在各种情况下都表现良好
  • 此指导可能会有所变化

示例:多工具

以下代码演示了如何在单个 .act() 调用中提供多个工具。

import math
import lmstudio as lms

def add(a: int, b: int) → int:
    """Given two numbers a and b, returns the sum of them."""
    return a + b

def is_prime(n: int) → bool:
    """Given a number n, returns True if n is a prime number."""
    if n < 2:
        return False
    sqrt = int(math.sqrt(n))
    for i in range(2, sqrt):
        if n % i == 0:
            return False
    return True

model = lms.llm("qwen2.5-7b-instruct")
model.act(
  "Is the result of 12345 + 45668 a prime? Think step by step.",
  [add, is_prime],
  on_message=print,
)

示例:带创建文件工具的聊天循环

以下代码创建了一个与可以创建文件的 LLM 代理的对话循环。

import readline # Enables input line editing
from pathlib import Path

import lmstudio as lms

def create_file(name: str, content: str):
    """Create a file with the given name and content."""
    dest_path = Path(name)
    if dest_path.exists():
        return "Error: File already exists."
    try:
        dest_path.write_text(content, encoding="utf-8")
    except Exception as exc:
        return "Error: {exc!r}"
    return "File created."

def print_fragment(fragment, round_index=0):
    # .act() supplies the round index as the second parameter
    # Setting a default value means the callback is also
    # compatible with .complete() and .respond().
    print(fragment.content, end="", flush=True)

model = lms.llm()
chat = lms.Chat("You are a task focused AI assistant")

while True:
    try:
        user_input = input("You (leave blank to exit): ")
    except EOFError:
        print()
        break
    if not user_input:
        break
    chat.add_user_message(user_input)
    print("Bot: ", end="", flush=True)
    model.act(
        chat,
        [create_file],
        on_message=chat.append,
        on_prediction_fragment=print_fragment,
    )
    print()

进度回调

与使用代理的工具进行复杂交互可能需要一些时间来处理。

任何预测请求的常规进度回调都可用,但预期功能与单轮预测的功能不同。

  • on_prompt_processing_progress:在每个预测轮次的提示处理期间调用。接收进度比率(浮点数)和轮次索引作为位置参数。
  • on_first_token:在每个预测轮次的提示处理完成后调用。接收轮次索引作为其唯一参数。
  • on_prediction_fragment:为客户端收到的每个预测片段调用。接收预测片段和轮次索引作为位置参数。
  • on_message:在每个预测轮次完成后,以及在每个工具调用请求完成后,以助手响应消息和工具结果消息的形式调用。旨在将收到的消息附加到聊天历史实例,因此接收轮次索引作为参数。

以下附加回调可用于监视预测轮次

  • on_round_start:在提交每个轮次的预测请求之前调用。接收轮次索引作为其唯一参数。
  • on_prediction_completed:在轮次预测完成后调用,但在任何请求的工具调用启动之前。接收轮次的预测结果作为其唯一参数。轮次预测结果是一个常规预测结果,带有一个额外的 round_index 属性。
  • on_round_end:在轮次的任何工具调用请求解决后调用。

最后,应用程序可以请求在代理发出无效工具请求时收到通知

  • handle_invalid_tool_request:当工具请求无法处理时调用。接收即将报告的异常,以及导致问题的原始工具请求。当未提供工具请求时,这纯粹是代理交互引发给定异常之前不可恢复错误的通知(允许应用程序 대신引发自己的异常)。当提供工具请求时,这表示异常的文本描述将作为该失败工具请求的结果返回给代理,而不是在本地引发。在这些情况下,回调可以返回 None 以指示应将错误描述发送给代理,在本地引发给定异常(或不同的异常),或者返回一个文本字符串,该字符串应代替错误描述发送给代理。

有关定义工具的更多详细信息,以及覆盖无效工具请求处理以在本地引发所有异常而不是将其传递回代理的示例,请参阅 工具定义

此页面的源代码可在 GitHub 上找到