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 调用是函数,而不是链。