趋近智
当你的Python工具完成任务后,它如何将结果呈现给大型语言模型(LLM),这与任务本身一样重要。LLM虽然擅长处理自然语言,但在接收外部数据时,更偏好可预测性和结构。简单地返回一段未区分的文本,可能导致误解,需要更复杂的提示才能解析,甚至让LLM忽略重要细节。有效地组织工具输出,对于构建可靠高效的智能体系统而言非常重要。
主要目标是让LLM理解和使用工具输出的工作尽可能简单。这通常意味着以机器易于解析且LLM便于“推理”的格式提供数据。
虽然工具在技术上可以输出纯文本,LLM通常也能理解,但结构化格式在一致性和可靠性方面更优。
JSON (JavaScript 对象表示法): 这是为LLM准备的工具输出中最受推荐和广泛采用的格式。
XML (可扩展标记语言): 如果你的工具与只提供XML的旧系统或API交互,你可能需要返回XML或进行转换。然而,如果可以选择,由于其简洁性以及在现代Web API中更普遍的使用,JSON通常是新工具开发的优选。
纯文本(附带注意事项): 对于结构极其简单的输出(例如,一个只返回单个数字或布尔状态的工具),纯文本可能足够。然而,一旦涉及多条信息,或者信息之间存在内在关联,JSON就会成为更好的选择。如果必须使用纯文本来处理复杂数据,请建立一个非常清晰、一致且易于解析的基于分隔符的系统,但请注意,这比JSON更容易导致LLM误解。
对于大多数自定义Python工具,JSON是推荐的输出格式。
“模式”(schema)指的是结构化输出的设计。一个精心设计的模式能确保LLM以可预测且有用的方式接收数据。
字段名(JSON中的键)应该一目了然。避免使用隐晦的缩写。如果一个字段代表用户的电子邮件地址,user_email或email_address远优于u_em或dat1。请记住,LLM会使用这些名称来理解值的含义。
在命名约定(例如,键使用snake_case或camelCase)和类似信息的数据类型方面保持一致性,无论是跨不同工具,还是在同一工具的各种输出中。如果用户ID在系统某部分是整数,那么它在任何地方都应该是整数。
使用适当的JSON数据类型:
true/false状态。包含LLM当前任务或后续步骤可能需要的所有信息。但是,请注意冗长。过大的输出可能会占用LLM上下文窗口中宝贵的token,并可能使LLM更难高效处理。如果工具生成大量数据,请考虑工具本身是否可以执行一些摘要或过滤,或者分页是否合适。
如果工具遇到可以优雅处理的错误,或者需要传达失败状态,输出结构应适应这种情况。工具可以返回一个指示成功或失败的JSON对象,而不是抛出导致智能体停止的异常(除非这是期望的行为)。
例如,一个成功的输出可能如下所示:
{
"status": "success",
"data": {
"user_id": "12345",
"username": "llm_dev"
}
}
错误输出则可能如下:
{
"status": "error",
"error_code": "USER_NOT_FOUND",
"message": "User with ID '67890' could not be found."
}
这使得LLM能够理解工具已执行但遇到了特定问题,然后LLM可以在其推理中使用这些信息。
让我们来看一个获取产品信息的工具。
一个不太理想、有些非结构化的文本输出:
Product: SuperWidget, Price: $29.99, In Stock: Yes, Features: Durable, Lightweight, Color: Blue.
LLM可能会解析这段文本,但其可靠性较低。如果“In Stock”是“No”怎么办?或者货币符号改变了呢?
同一产品的良好结构化JSON输出:
{
"product_name": "SuperWidget",
"price": 29.99,
"currency": "USD",
"in_stock": true,
"features": ["Durable", "Lightweight"],
"specifications": {
"color": "Blue",
"weight_grams": 150
}
}
此JSON输出明确。LLM可以轻松提取价格、检查库存状态或列出功能。
对于返回多个项目(如搜索结果)的工具:
{
"query_terms": ["python", "async", "web server"],
"results_count": 2,
"items": [
{
"title": "Building Async Web Servers with Python",
"url": "https://example.com/async-servers",
"snippet": "An in-depth guide to using asyncio and libraries like aiohttp...",
"relevance_score": 0.85
},
{
"title": "Understanding Python's Async/Await",
"url": "https://another-site.org/python-async",
"snippet": "A foundational explanation of asynchronous programming concepts in Python.",
"relevance_score": 0.72
}
]
}
在此,结构清楚地将每个搜索结果划分为数组中的一个对象,每个对象都拥有自己的一组属性。
Python的标准库使得生成JSON变得简单直接。json模块是你的主要工具。
import json
def get_product_info_tool(product_id: str):
# 假设从数据库或API获取数据
if product_id == "SW001":
product_data = {
"product_name": "SuperWidget",
"price": 29.99,
"currency": "USD",
"in_stock": True, # Python布尔值
"features": ["Durable", "Lightweight"],
"specifications": {
"color": "Blue",
"weight_grams": 150
}
}
# 将Python字典序列化为JSON字符串
return json.dumps(product_data)
else:
error_data = {
"status": "error",
"error_code": "PRODUCT_NOT_FOUND",
"message": f"Product with ID '{product_id}' not found."
}
return json.dumps(error_data)
# 使用示例:
output_json = get_product_info_tool("SW001")
print(output_json)
# 输出:
# {"product_name": "SuperWidget", "price": 29.99, "currency": "USD", "in_stock": true, "features": ["Durable", "Lightweight"], "specifications": {"color": "Blue", "weight_grams": 150}}
output_error_json = get_product_info_tool("XYZ789")
print(output_error_json)
# 输出:
# {"status": "error", "error_code": "PRODUCT_NOT_FOUND", "message": "Product with ID 'XYZ789' not found."}
请注意Python的True是如何转换为JSON的true的。json.dumps()函数处理这些转换。
对于更复杂的情况,特别是当处理许多不同的输出结构或在序列化之前需要验证输出数据时,像Pydantic这样的库非常有帮助。Pydantic允许你使用Python类型提示定义数据模型。这些模型随后可以解析输入数据并序列化为JSON,确保你的输出符合预定义的模式。
from typing import List, Dict, Optional
from pydantic import BaseModel
import json
# 为我们的产品结构定义Pydantic模型
class ProductSpecifications(BaseModel):
color: str
weight_grams: int
class ProductInfo(BaseModel):
product_name: str
price: float
currency: str
in_stock: bool
features: List[str]
specifications: ProductSpecifications
class ErrorResponse(BaseModel):
status: str = "error"
error_code: str
message: str
def get_product_info_tool_pydantic(product_id: str) -> str:
if product_id == "SW001":
product_data = ProductInfo(
product_name="SuperWidget",
price=29.99,
currency="USD",
in_stock=True,
features=["Durable", "Lightweight"],
specifications=ProductSpecifications(color="Blue", weight_grams=150)
)
# Pydantic模型具有.model_dump_json()方法(或Pydantic v1中的.json())
return product_data.model_dump_json()
else:
error_data = ErrorResponse(
error_code="PRODUCT_NOT_FOUND",
message=f"Product with ID '{product_id}' not found."
)
return error_data.model_dump_json()
# print(get_product_info_tool_pydantic("SW001"))
使用Pydantic通过验证你即将序列化的数据是否符合预期的结构和类型,增加了一层健壮性。
以下图表说明了使用结构化输出时,数据从Python工具到LLM的典型流程:
当使用结构化JSON输出时,从工具执行到LLM接收的数据流。
仅仅返回JSON并不总是足够的。LLM需要知道期待什么以及如何使用它。这通常通过以下方式实现:
如果你的工具可能返回大量数据:
"results_truncated": true, "total_available_results": 1000)。如果你的工具支持分页,输出可以包含如何获取下一页的信息(例如,next_page_token: "nextToken123")。通过精心组织工具输出,你可以显著提升LLM智能体的可靠性和能力。清晰、可预测的JSON输出使得LLM更像是精确的程序化组件,而不仅仅是一个文本处理器,从而带来更强大、更可靠的应用。在你持续开发自定义Python工具时,请始终考虑LLM将如何最好地接收你的工具提供的信息。
这部分内容有帮助吗?
© 2026 ApX Machine Learning用心打造