OpenAI兼容的LLM工具调用转发器,使得不支持原生工具调用的模型可以通过提示词工程实现function calling功能。
- ✅ 完全OpenAI API兼容 - 客户端无需修改代码
- ✅ 自动工具转换 - 将
tools参数转换为系统提示词(XML格式) - ✅ XML工具调用解析 - 解析模型输出的
<tool_use>标签 - ✅ 标准格式转换 - 转换为OpenAI
tool_calls格式 - ✅ 自定义工具占位符 - 支持YAML配置
- ✅ 双向API Key支持 - 上游和下游都支持API Key
- ✅ YAML配置 - 支持环境变量引用(
${VAR_NAME}) - ✅ 流式响应 - 完整SSE支持
- ✅ FastAPI高性能 - 异步HTTP服务器
- ✅ Python API - 可作为库使用
客户端请求
↓
解析 tools 参数
↓
转换为XML格式系统提示词
↓
转发到上游LLM(如硅基流动)
↓
接收模型响应
↓
解析 <tool_use> XML标签
↓
转换为 OpenAI tool_calls 格式
↓
返回给客户端
git clone https://github.com/your-repo/homo-sapiens.git
cd homo-sapienspip install -r requirements.txt或使用pip安装:
pip install -e .配置文件位于 config/config.yaml:
# 服务器配置
server:
host: "127.0.0.1"
port: 8888
api_key: "${PROXY_API_KEY:default-key}"
require_api_key: false
# 上游LLM配置
upstream:
url: "https://api.siliconflow.cn/v1"
api_key: "${SILICONFLOW_API_KEY:}"
model: "Qwen/Qwen2-7B-Instruct"
timeout: 120
# 工具配置
tools:
placeholder: "{tools_xml}"
enabled: true
# 响应配置
response:
stream_enabled: true
stream_delay: 0
# 日志配置
logging:
level: "INFO"配置文件支持环境变量引用:
${VAR_NAME}- 必须设置的环境变量${VAR_NAME:default}- 可选环境变量,有默认值
示例:
# 设置上游API Key(硅基流动)
export SILICONFLOW_API_KEY="sk-xxxxx"
# 设置下游API Key(可选)
export PROXY_API_KEY="my-secret-key"python -m llm_proxy.server或使用命令:
llm-proxy服务器将在 http://127.0.0.1:8888 启动。
使用OpenAI SDK连接:
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:8888/v1",
api_key="default-key"
)
response = client.chat.completions.create(
model="Qwen/Qwen2-7B-Instruct",
messages=[
{"role": "user", "content": "你好!"}
]
)
print(response.choices[0].message.content)from openai import OpenAI
import json
client = OpenAI(
base_url="http://127.0.0.1:8888/v1",
api_key="default-key"
)
# 定义工具
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取指定城市的当前天气",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "城市名称"
}
},
"required": ["city"]
}
}
}
]
# 发送请求
response = client.chat.completions.create(
model="Qwen/Qwen2-7B-Instruct",
messages=[
{"role": "user", "content": "北京现在天气怎么样?"}
],
tools=tools
)
message = response.choices[0].message
# 检查工具调用
if message.tool_calls:
for tool_call in message.tool_calls:
print(f"工具: {tool_call.function.name}")
print(f"参数: {tool_call.function.arguments}")
# 执行工具
args = json.loads(tool_call.function.arguments)
result = execute_get_weather(args['city'])
# 发送工具结果
response_2 = client.chat.completions.create(
model="Qwen/Qwen2-7B-Instruct",
messages=[
{"role": "user", "content": "北京现在天气怎么样?"},
message,
{
"role": "tool",
"tool_call_id": tool_call.id,
"content": result
}
],
tools=tools
)
print(response_2.choices[0].message.content)stream = client.chat.completions.create(
model="Qwen/Qwen2-7B-Instruct",
messages=[{"role": "user", "content": "介绍一下Python"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end='', flush=True)运行完整的测试套件:
# 确保设置了上游API Key
export SILICONFLOW_API_KEY="your-key"
# 启动服务器
python -m llm_proxy.server &
# 运行测试
python examples/test_proxy.py测试包括:
- ✅ 简单聊天(不使用工具)
- ✅ 工具调用
- ✅ 流式响应
- ✅ 工具结果处理
homo-sapiens/
├── llm_proxy/ # 主要实现
│ ├── __init__.py # 包初始化
│ ├── server.py # FastAPI HTTP服务器
│ ├── proxy.py # 转发器核心逻辑
│ ├── tool_formatter.py # 工具格式化器
│ ├── xml_parser.py # XML解析器
│ ├── models.py # Pydantic数据模型
│ └── config_loader.py # YAML配置加载器
├── config/
│ └── config.yaml # 配置文件
├── examples/ # 示例代码
│ ├── client_example.py # 客户端示例
│ └── test_proxy.py # 测试脚本
├── reference/ # 参考实现
│ ├── add_tools_to_prompt.py
│ └── tool_use_by_prompt_chain.txt
├── requirements.txt # 依赖
└── pyproject.toml # 项目配置
{
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取天气",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
}
}
}
}
]
}模型会看到以下格式的提示词:
<tools>
<tool>
<name>get_weather</name>
<description>获取天气</description>
<arguments>
{"type":"object","properties":{"city":{"type":"string"}}}
</arguments>
</tool>
</tools>
工具调用格式:
<tool_use>
<name>{工具名称}</name>
<arguments>{json格式参数}</arguments>
</tool_use>{
"message": {
"role": "assistant",
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"北京\"}"
}
}
]
}
}获取服务信息。
列出可用模型。
聊天完成接口(OpenAI兼容)。
支持参数:
model- 模型名称messages- 消息数组tools- 工具定义(可选)stream- 是否流式响应(默认false)temperature- 温度参数max_tokens- 最大令牌数
目前已测试的上游服务:
- ✅ 硅基流动 (SiliconFlow) - https://api.siliconflow.cn/v1
- ✅ Ollama - http://localhost:11434/v1
- ✅ 其他OpenAI兼容API - 如vLLM、localAI等
A: 确保上游模型有足够的上下文长度,并且系统提示词清晰。有些模型可能需要更多的提示词指导。
A: 查看服务器日志,可以看到转换后的请求和响应。也可以在测试脚本中添加print语句。
A: 支持。流式响应会实时解析<tool_use>标签并转换为tool_calls格式。
A: 可以。在config/config.yaml中修改tools.placeholder配置。
MIT License
欢迎提交Issue和Pull Request!