最近在开发Dria-Agent-α时,我们尝试了一种全新的LLM工具交互方式——Pythonic Function Calling。与传统的JSON Schema函数调用不同,这种方法让LLM直接输出Python代码来操作工具。想象一下,当你让AI助手安排会议时,它不再需要多次往返确认,而是能像程序员一样写出完整的条件判断和操作流程。这正是我们在实际项目中验证的技术突破。
传统JSON函数调用的局限性很明显:多轮对话效率低下、复杂逻辑难以表达、状态管理支离破碎。而Python作为LLM预训练数据中的高频语言,其代码表达能力与自然语言的相似性,使其成为工具交互的理想媒介。我们的测试表明,使用Pythonic Function Calling的代理模型,在复杂任务中的完成率比JSON方案高出37%,且平均交互轮次减少到1.2轮。
LLM在代码数据上的预训练使其对Python语法有深刻理解。研究表明(Ruis et al., 2024),程序性知识正是驱动LLM推理的核心要素。当给出以下会议安排需求时:
"明天10-12点如果有空,请与导师安排会议并添加提醒"
传统JSON方案需要:
而Python方案只需单次生成:
python复制from datetime import datetime, timedelta
tomorrow = (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d")
if check_availability(tomorrow, "10:00", "12:00"):
result = make_appointment(tomorrow, "10:00", "12:00", "导师会议")
if result["appointment_made"]:
add_to_reminders("明天10点导师会议")
我们开发了专用的代码执行器exec-python,其核心功能包括:
执行示例:
python复制x = [1,2]
y = [2,3]
z = pair_sum(x, y)
将输出:
json复制{
"function_results": {"pair_sum": ["z"]},
"variables": {"x": [1,2], "y": [2,3], "z": [3,5]},
"errors": []
}
关键实现技巧:使用AST解析而非直接eval,防止注入攻击;对耗时操作添加watchdog定时中断。
传统方法先定义工具再生成用例,导致大量不切实际的样本。我们采用的三阶段流程:
python复制def validate_permission_flow():
# 测试权限修改的完整流程
original = check_user_permissions("alex", r"\\server\shared")
assert modify_folder_permissions("alex", r"\\server\shared", {"read":True})
assert verify_folder_access("alex", r"\\server\shared")
我们设计了渐进式训练策略:
| 阶段 | 重点能力 | 数据特征 |
|---|---|---|
| 1 | 基础语法 | 单函数调用 |
| 2 | 条件逻辑 | if-else分支 |
| 3 | 状态管理 | 跨多行的变量引用 |
| 4 | 异常处理 | try-catch块 |
| 5 | 复杂编排 | 混合控制流 |
在Qwen2.5架构基础上,我们做了以下改进:
python复制def custom_loss(y_true, y_pred):
# 增强函数名和关键字的准确性
key_terms_mask = create_term_mask(y_true)
return tf.reduce_mean(key_terms_mask * categorical_crossentropy(y_true, y_pred))
实测显示,7B模型在以下任务上表现优异:
| 任务类型 | 准确率 |
|---|---|
| 单函数直接调用 | 98.2% |
| 双重条件嵌套 | 89.7% |
| 带异常处理的流程 | 83.1% |
| 跨3+函数的编排任务 | 76.4% |
资源限制:
python复制import resource
resource.setrlimit(resource.RLIMIT_CPU, (1, 1)) # 限制1秒CPU时间
resource.setrlimit(resource.RLIMIT_AS, (256*1024*1024,)) # 256MB内存
敏感操作拦截:
python复制BLACKLIST = ["open", "eval", "os.system"]
class SafeTransformer(ast.NodeTransformer):
def visit_Call(self, node):
if isinstance(node.func, ast.Name) and node.func.id in BLACKLIST:
raise SecurityError(f"禁止调用 {node.func.id}")
return node
在Kubernetes部署时建议配置:
yaml复制resources:
limits:
cpu: "2"
memory: "8Gi"
requests:
cpu: "500m"
memory: "2Gi"
autoscaling:
targetCPUUtilizationPercentage: 60
minReplicas: 3
实测发现,当QPS>50时,7B模型的响应时间会从800ms陡增至2s以上,建议使用3B模型处理高并发请求。
安装基础包:
bash复制pip install dria-agent-alpha
最小化集成代码:
python复制from dria_agent import PythonicAgent
agent = PythonicAgent(
model_size="3b", # or "7b"
api_key="your_key",
functions=[check_availability, make_appointment] # 注册可用函数
)
response = agent.run(
"明天上午如果9-11点有空,安排团队周会并通知所有人",
temperature=0.3 # 对确定性要求高的任务降低随机性
)
print(response.execution_log)
典型的执行日志包含:
python复制{
"generated_code": "...",
"variables": {
"time_slot": "2025-03-20 09:00",
"is_available": True,
"invitees": ["alice@example.com", "bob@example.com"]
},
"function_calls": [
{
"name": "check_availability",
"args": {"day": "2025-03-20", "start": "09:00", "end": "11:00"},
"return": True
}
],
"warnings": ["未找到bob@example.com的日历权限"]
}
常见问题排查:
我们正在试验的技术突破:
python复制def compute_reward(trajectory):
# 基于代码执行结果计算奖励
coverage = len(trajectory['used_functions']) / len(required_functions)
correctness = checklist_score(trajectory['outputs'])
return 0.6 * correctness + 0.4 * coverage
在测试中的Dria-Agent-β已展现以下能力:
这种Pythonic的交互范式正在重塑我们对LLM能力的认知。当模型能像开发者一样思考,人与AI的协作将进入全新阶段。我们在实际部署中发现,最有效的提示词往往包含明确的上下文和预期代码结构,例如:
"请用Python代码处理这个需求,先验证条件再执行操作,最后处理异常情况。可用函数:list_files(), analyze_content()"
这种引导方式能让模型产出更符合工程实践的代码。随着代码生成可靠性的提升,我们正将这一技术应用于自动化测试、数据流水线等更多场景,期待看到开发者社区的创新应用。