内容
# 开放代码大语言模型代理
[](https://www.npmjs.com/package/opencode-llm-proxy)
[](https://www.npmjs.com/package/opencode-llm-proxy)
[](https://github.com/KochC/opencode-llm-proxy/actions/workflows/ci.yml)
[](https://opensource.org/licenses/MIT)
**一个本地端点。您可以访问的所有模型。任意 API 格式。包含工具调用。**
开放代码大语言模型代理是 [OpenCode](https://opencode.ai) 的一个插件,它在 `http://127.0.0.1:4010` 上启动一个本地 HTTP 服务器。它在您的工具所使用的 API 格式和 OpenCode 配置的任意 LLM 提供商之间进行转换 - 这样您就不需要重新配置相同的模型两次。
```
您的工具(OpenAI / Anthropic / Gemini SDK,编码代理等)
│
▼ http://127.0.0.1:4010
开放代码大语言模型代理
│
▼ OpenCode SDK
GitHub Copilot · Anthropic · Gemini · Ollama · OpenRouter · Bedrock · …
```
**支持的 API 格式 — 所有格式都支持流式传输和 [工具调用](#工具调用):**
| 格式 | 端点 |
|---|---|
| OpenAI 聊天补全 | `POST /v1/chat/completions` |
| OpenAI 响应 API | `POST /v1/responses` |
| Anthropic 消息 API | `POST /v1/messages` |
| Google Gemini | `POST /v1beta/models/:model:generateContent` |
**✨ 工具调用适用于所有四种格式** — 将编码代理(Claude Code、Cursor、Continue、Cline、您自己的代理循环...)指向代理,其 `tools` / `tool_choice` 调用被转换为 OpenCode 配置的模型,并返回带有真实 `tool_calls` / `tool_use` / `functionCall` 响应的内容。请参阅 [工具调用](#工具调用)。
---
## 目录
- [为什么](#为什么)
- [快速入门](#快速入门)
- [安装](#安装)
- [配置](#配置)
- [工具调用](#工具调用)
- [与 SDK 和工具一起使用](#与-sdk-和工具一起使用)
- [查找模型 ID](#查找模型-id)
- [API 参考](#api-参考)
- [工作原理](#工作原理)
- [限制](#限制)
- [许可证](#许可证)
---
## 为什么
大多数 LLM 工具只支持一种 API 方言。OpenCode 已经管理着您使用的所有提供商的连接。这个代理连接了两者 — 您的工具保持不变,您可以在一个地方更改使用的模型。
**它解决的常见情况:
- 您拥有 **GitHub Copilot** 订阅。Open WebUI、Chatbox 或 VS Code 扩展只接受 OpenAI 兼容的 URL。将它们指向代理 — 完成。
- 您在本地运行 **Ollama**。您的 Python 脚本使用 OpenAI SDK。将 `base_url` 设置为代理并直接使用 Ollama 模型 ID。
- 您想在**不更改代码的情况下切换模型**。您的应用程序与代理通信;您在 OpenCode 配置中更改模型。
- 您想在 **局域网上共享您的模型**。在 `0.0.0.0` 上公开代理并将 URL 提供给队友。
- 您使用 **Anthropic SDK** 但想通过 GitHub Copilot 或 Bedrock 进行路由。无需更改 SDK 代码 — 只需将其指向代理。
- 您正在构建或运行需要针对 OpenCode 配置的模型进行真实工具/函数调用(读取文件、运行 shell 命令等)的**编码代理**。请参阅 [工具调用](#工具调用)。
---
## 快速入门
```bash
npm install opencode-llm-proxy
```
添加到 `opencode.json`:
```json
{
"plugin": ["opencode-llm-proxy"]
}
```
启动 OpenCode — 代理将自动启动:
```bash
opencode
```
发送请求:
```bash
curl http://127.0.0.1:4010/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "github-copilot/claude-sonnet-4.6",
"messages": [{"role": "user", "content": "你好!"}]
}'
```
---
## 安装
### npm 插件(推荐)
```bash
npm install opencode-llm-proxy
```
添加到全局 `~/.config/opencode/opencode.json`(在所有地方都有效)或项目级 `opencode.json`:
```json
{
"plugin": ["opencode-llm-proxy"]
}
```
### 复制文件
**全局** — 为每个 OpenCode 会话加载:
```bash
curl -o ~/.config/opencode/plugins/llm-proxy.js \
https://raw.githubusercontent.com/KochC/opencode-llm-proxy/main/index.js
```
**按项目** — 仅在该目录中加载:
```bash
mkdir -p .opencode/plugins
curl -o .opencode/plugins/llm-proxy.js \
https://raw.githubusercontent.com/KochC/opencode-llm-proxy/main/index.js
```
> 复制 `index.js` 适用于除 [工具调用](#工具调用) 之外的所有功能,工具调用还需要 `mcp-tool-bridge.js`。如果您需要工具调用,请使用 npm 插件安装方法。
---
## 配置
| 变量 | 默认值 | 描述 |
|---|---|---|
| `OPENCODE_LLM_PROXY_HOST` | `127.0.0.1` | 绑定地址。`0.0.0.0` 以在局域网或 Docker 上公开。 |
| `OPENCODE_LLM_PROXY_PORT` | `4010` | TCP 端口。 |
| `OPENCODE_LLM_PROXY_TOKEN` | _(未设置)_ | 每个请求所需的 Bearer 令牌。未设置 = 无身份验证。 |
| `OPENCODE_LLM_PROXY_CORS_ORIGIN` | `*` | 浏览器客户端的 `Access-Control-Allow-Origin` 值。 |
| `OPENCODE_LLM_PROXY_TOOL_BRIDGE_POOL_SIZE` | `8` | 使用 [工具调用](#工具调用) 的最大并发请求数。 |
```bash
OPENCODE_LLM_PROXY_HOST=0.0.0.0 \
OPENCODE_LLM_PROXY_TOKEN=my-secret \
opencode
```
---
## 工具调用
代理支持所有四种 API 格式的真实工具/函数调用 — OpenAI 函数工具(`/v1/chat/completions` 和 `/v1/responses` 上的 `tools`)、Anthropic 工具(`/v1/messages` 上的 `tools`)和 Gemini 函数声明(`:generateContent`/`:streamGenerateContent` 上的 `tools`)。这使得编码代理和其他使用工具的客户端可以通过代理工作,而不仅仅是普通的聊天。
```bash
curl http://127.0.0.1:4010/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "github-copilot/claude-sonnet-4.6",
"messages": [{"role": "user", "content": "纽约的天气怎么样?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "获取一个城市的当前天气",
"parameters": {
"type": "object",
"properties": { "city": { "type": "string" } },
"required": ["city"]
}
}
}]
}'
```
```json
{
"choices": [{
"finish_reason": "tool_calls",
"message": {
"role": "assistant",
"content": null,
"tool_calls": [{
"id": "call_...",
"type": "function",
"function": { "name": "get_weather", "arguments": "{\"city\":\"NYC\"}" }
}]
}
}]
}
```
在下一个请求中,将工具的结果发送回(`role: "tool"` / `tool_result` / `functionResponse`,根据您的 API 约定)以及完整的对话历史记录,就像任何其他多轮请求一样 — 代理在调用之间是无状态的。
### 工具调用的底层工作原理
OpenCode 自己的代理循环始终在服务器端执行工具,因此没有将“客户端执行”的工具调用传递给它的本地概念。为了弥合这一差距,当请求包含 `tools` 时:
1. 代理动态注册一个小型本地 [MCP](https://opencode.ai/docs/mcp-servers/) 服务器,其工具列表正是您声明的工具架构(请参见 `mcp-tool-bridge.js`)。
2. 仅为该提示调用启用这些工具 — 所有内置 OpenCode 工具保持禁用状态,与以前一样。
3. 当模型建议调用其中一个工具时,代理会立即中止 OpenCode 会话(在桥的空操作处理程序被咨询之前),并将捕获的调用名称 + 参数转换为您的 API 的工具调用形状 — `tool_calls`(OpenAI),`tool_use`(Anthropic)或 `functionCall` 部分(Gemini)— 而不是文本答案。
### 注意事项和当前限制
- 每个回合一个工具调用 — 不支持并行/多个同时工具调用。
- `tool_choice: "none"`(OpenAI/Gemini `mode: "NONE"`/Anthropic `type: "none"`)为该请求禁用工具调用;强制使用特定命名工具是支持的。
- 桥接服务器从一个小固定大小的池(`px_tools_0`、`px_tools_1`,...)中重用,而不是为每个请求注册新的池,因为 OpenCode 的服务器 API 没有端点可以在添加后注销 MCP 服务器。如果您期望有超过 8 个并发的飞行中工具调用请求,请使用 `OPENCODE_LLM_PROXY_TOOL_BRIDGE_POOL_SIZE`(默认为 `8`)进行配置。
- 桥接进程使用 `node` 启动,因此 `node` 必须在 OpenCode 运行的任何地方都在 `PATH` 上。
---
## 与 SDK 和工具一起使用
### OpenAI SDK(JS/TS)
```javascript
import OpenAI from "openai"
const client = new OpenAI({
baseURL: "http://127.0.0.1:4010/v1",
apiKey: "unused",
})
const response = await client.chat.completions.create({
model: "github-copilot/claude-sonnet-4.6",
messages: [{ role: "user", content: "解释递归。" }],
})
```
### OpenAI SDK(Python)
```python
from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:4010/v1", api_key="unused")
response = client.chat.completions.create(
model="ollama/qwen2.5-coder",
messages=[{"role": "user", "content": "编写一个反转字符串的 Python 函数。"}],
)
print(response.choices[0].message.content)
```
### Anthropic SDK(Python)
```python
import anthropic
client = anthropic.Anthropic(
base_url="http://127.0.0.1:4010",
api_key="unused",
)
message = client.messages.create(
model="anthropic/claude-3-5-sonnet",
max_tokens=1024,
messages=[{"role": "user", "content": "什么是勾股定理?"}],
)
print(message.content[0].text)
```
### Anthropic SDK(JS/TS)
```javascript
import Anthropic from "@anthropic-ai/sdk"
const client = new Anthropic({
baseURL: "http://127.0.0.1:4010",
apiKey: "unused",
})
const message = await client.messages.create({
model: "anthropic/claude-opus-4",
max_tokens: 1024,
messages: [{ role: "user", content: "解释 async/await。" }],
})
```
### Google Generative AI SDK(JS/TS)
```javascript
import { GoogleGenerativeAI } from "@google/generative-ai"
const genAI = new GoogleGenerativeAI("unused", {
baseUrl: "http://127.0.0.1:4010",
})
const model = genAI.getGenerativeModel({ model: "google/gemini-2.0-flash" })
const result = await model.generateContent("什么是机器学习?")
console.log(result.response.text())
```
### LangChain(Python)
```python
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="anthropic/claude-3-5-sonnet",
openai_api_base="http://127.0.0.1:4010/v1",
openai_api_key="unused",
)
response = llm.invoke("什么是 SOLID 原则?")
print(response.content)
```
### Open WebUI
1. 设置 → 连接 → OpenAI API
2. 将 **API 基础 URL** 设置为 `http://127.0.0.1:4010/v1`
3. 留空 API 密钥(或设置为您的 `OPENCODE_LLM_PROXY_TOKEN`)
4. 保存 — 您的所有 OpenCode 模型都会出现在模型选择器中
> 在 Docker 中运行 Open WebUI?使用 `http://host.docker.internal:4010/v1` 并设置 `OPENCODE_LLM_PROXY_HOST=0.0.0.0`。
### Chatbox
设置 → AI 提供商 → OpenAI API → 将 **API 主机** 设置为 `http://127.0.0.1:4010`。
### Continue(VS Code / JetBrains)
在 `~/.continue/config.json` 中:
```json
{
"models": [
{
"title": "通过 OpenCode 的 Claude",
"provider": "openai",
"model": "anthropic/claude-3-5-sonnet",
"apiBase": "http://127.0.0.1:4010/v1",
"apiKey": "unused"
}
]
}
```
### Zed
在 `~/.config/zed/settings.json` 中:
```json
{
"language_models": {
"openai": {
"api_url": "http://127.0.0.1:4010/v1",
"available_models": [
{
"name": "github-copilot/claude-sonnet-4.6",
"display_name": "Claude (OpenCode)",
"max_tokens": 8096
}
]
}
}
}
```
---
## 查找模型 ID
```bash
curl http://127.0.0.1:4010/v1/models | jq '.data[].id'
# "github-copilot/claude-sonnet-4.6"
# "anthropic/claude-3-5-sonnet"
# "ollama/qwen2.5-coder"
# ...
```
使用 `provider/model` 以提高清晰度。裸模型 ID(例如 `gpt-4o`)如果在您的提供商中无歧义,则可以使用。
要强制指定提供商而不更改模型字符串,请添加:
```
x-opencode-provider: anthropic
```
---
## API 参考
### GET /health
```json
{ "healthy": true, "service": "opencode-openai-proxy" }
```
### GET /v1/models
返回 OpenAI 列表格式中所有已配置提供商的模型。
### POST /v1/chat/completions
OpenAI 聊天补全。必填字段:`model`、`messages`。可选:`stream`、`temperature`、`max_tokens`、`tools`、`tool_choice`。
### POST /v1/responses
OpenAI 响应 API。必填字段:`model`、`input`。可选:`instructions`、`stream`、`max_output_tokens`、`tools`、`tool_choice`。
### POST /v1/messages
Anthropic 消息 API。必填字段:`model`、`messages`。可选:`system`(字符串或 `{type: "text", text: string}` 内容块数组)、`max_tokens`、`stream`、`tools`、`tool_choice`。
错误以 Anthropic 格式返回:`{ "type": "error", "error": { "type": "...", "message": "..." } }`。
### POST /v1beta/models/:model:generateContent
Google Gemini 非流式。URL 路径中的模型名称。必填字段:`contents`。可选:`systemInstruction`、`generationConfig`、`tools`、`toolConfig`。
### POST /v1beta/models/:model:streamGenerateContent
与上述相同,返回以换行分隔的 JSON 流。
---
## 工作原理
每个请求:
1. 如果设置了 `OPENCODE_LLM_PROXY_TOKEN`,则进行身份验证
2. 解析其模型 — `provider/model`、裸模型 ID 或 Gemini URL 路径
3. 创建临时 OpenCode 会话(在会话列表中可见)
4. 通过 `client.session.prompt` / `client.session.promptAsync` 发送提示
5. 以与请求相同的格式返回响应
流式传输使用 OpenCode 的 `client.event.subscribe()` SSE 流。文本增量实时转发。
---
## 限制
- 仅限文本 — 图像、音频和文件输入将被忽略
- 无跨请求会话状态 — 每次请求发送完整的对话历史记录
- 温度和最大令牌数是建议性的(作为系统提示传递)
- 工具调用支持每个回合一个调用 — 请参见上面的 [工具调用](#工具调用)
---
## 许可证
MIT
连接信息
猜你喜欢
暂无推荐服务器