跳转到主要内容

Documentation Index

Fetch the complete documentation index at: https://simplellmfunc.cn/llms.txt

Use this file to discover all available pages before exploring further.

构建第一个 Agent

本指南构建一个简单的 Agent,它可以使用工具来回答问题。你将看到完整的循环:用户消息 → LLM 推理 → 工具调用 → 工具结果 → 最终响应。

定义工具

工具是用 @tool 装饰的异步函数:
from SimpleLLMFunc import tool


@tool
async def search_docs(query: str) -> str:
    """
    搜索文档中的相关信息。

    Args:
        query: 搜索查询。

    Returns:
        匹配的文档摘录。

    Best Practices:
        - 使用具体、聚焦的查询。
        - 优先使用精确术语而非模糊描述。
    """
    if "install" in query.lower():
        return "安装方式: pip install SimpleLLMFunc"
    return f"未找到结果: {query}"
要点:
  • 工具必须是 async def
  • 文档字符串成为 LLM 看到的工具描述
  • Best Practices 部分会被注入到系统提示词中作为使用指南
  • 返回类型注解告诉框架期望什么

定义 Agent

from SimpleLLMFunc import OpenAICompatible, llm_chat

models = OpenAICompatible.load_from_json_file("provider.json")
llm = models["openrouter"]["openai/gpt-4o"]


@llm_chat(llm_interface=llm, toolkit=[search_docs], stream=True)
async def assistant(message: str, history: list | None = None):
    """
    你是一个有帮助的文档助手。
    需要具体信息时使用搜索工具回答问题。
    简洁直接。
    """
    pass
要点:
  • @llm_chat 创建多轮 Agent(相对于单次调用的 @llm_function
  • toolkit=[...] 让 Agent 可以使用工具
  • stream=True 启用流式响应
  • history 参数名是特殊的——框架通过它管理对话状态
  • 文档字符串就是 Agent 的系统提示词

运行并消费事件

@llm_chat 返回 ReactOutput 的异步生成器——包含响应片段或生命周期事件:
import asyncio
from SimpleLLMFunc.hooks import is_response_yield, is_event_yield


async def main():
    history = []

    async for output in assistant("如何安装 SimpleLLMFunc?", history):
        if is_response_yield(output):
            print(output.response, end="")
            history = output.messages
        elif is_event_yield(output):
            event = output.event

    print()


asyncio.run(main())

底层发生了什么

1. 用户消息 "如何安装 SimpleLLMFunc?" → 编译为 LLM 请求
2. LLM 决定调用 search_docs(query="install SimpleLLMFunc")
3. 框架执行工具,获取结果
4. 结果通过内部运行时补丁应用到对话记录
5. 上下文重新编译,发回 LLM
6. LLM 使用工具结果生成最终响应
7. 响应以 ReactOutput 事件流式返回
这就是 ReAct 循环——推理、行动、观察、重复。框架处理所有这些。你只定义了一个函数签名和一个工具。

添加更多工具

@tool
async def calculate(expression: str) -> float:
    """
    计算数学表达式。

    Args:
        expression: Python 数学表达式(如 "2 ** 10")。

    Returns:
        数值结果。

    Best Practices:
        - 使用 Python 语法进行数学运算。
        - 保持表达式简单可读。
    """
    return float(eval(expression))


@llm_chat(llm_interface=llm, toolkit=[search_docs, calculate], stream=True)
async def assistant(message: str, history: list | None = None):
    """你是一个可以搜索文档和做数学计算的助手。"""
    pass

下一步

多轮对话

管理更长的对话,包括历史和流式输出。

为什么这样设计?

理解为什么 LLM 调用是函数,而不是链。