多模型融合架构
统一调度 Kimi / Qwen / GLM 等后端能力,支持显式模型与 Hetu 自动优选,覆盖长文本、中文对话、代码等场景。
河图
河图(Hetu)定位为多模型融合智能平台:统一接入、统一调度、统一观测,提供更稳的模型可用性与更低迁移成本。
统一调度 Kimi / Qwen / GLM 等后端能力,支持显式模型与 Hetu 自动优选,覆盖长文本、中文对话、代码等场景。
请求与响应结构兼容 OpenAI Chat Completions,可直接使用 OpenAI SDK 与主流 IDE 插件,降低迁移与联调成本。
支持非流式与 SSE 流式输出,兼顾实时体验与工程可控;可用于聊天、IDE 协作与服务端自动化场景。
标准化错误码体系 + Trace ID 追踪,结合配额和限流语义,便于定位问题、归因上游、完善监控告警。
原生适配 Cursor、VS Code 等开发工具,统一 Base URL + SK 即可接入,提升研发与协作效率。
河图(Hetu)采用多模型融合架构,统一调度 Kimi、Qwen、GLM 等后端能力。你可以显式指定模型,也可以使用 Auto / Hetu 走自动选模。
| 模型 | 上下文窗口 | 最大输出 | 后端 | 特点 |
|---|---|---|---|---|
| kimi-k2.5 | 256K | 8192 | Kimi | 旗舰模型,擅长长上下文与复杂推理 |
| qwen3.5-max | 128K | 8192 | Qwen | 中文理解与代码任务表现稳定 |
| qwen3.5-plus | 128K | 4096 | Qwen | 性能与成本均衡 |
| glm-5 | 128K | 8192 | GLM | 中文对话、知识问答能力突出 |
| glm-5-flash | 128K | 4096 | GLM | 轻量快速,适合低延迟场景 |
河图 API 在请求/响应格式上兼容 OpenAI。
| 项 | 值 |
|---|---|
| 认证头 | Authorization: Bearer <SK> |
| 推荐 SDK Base URL | https://www.libav.cn/api/v1 |
| 典型 HTTP 端点 | POST /api/v1/chat/completions |
以下为 OpenAI Chat Completions 兼容响应的常见结构。上游若返回额外字段(例如缓存命中相关字段),网关通常会尽量透传;未返回的字段不会强行补齐。
HTTP 200,Content-Type: application/json。
{
"id": "cmpl-04ea926191a14749b7f2c7a48a68abc6",
"object": "chat.completion",
"created": 1698999496,
"model": "kimi-k2.6",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "你好,李雷!1+1等于2。如果你有其他问题,请随时提问!"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 19,
"completion_tokens": 21,
"total_tokens": 40,
"cached_tokens": 10
}
}
HTTP 200,通常为 Content-Type: text/event-stream。每个事件以 data: 开头;最后一帧常为带 finish_reason 的 chunk,并可能在同一帧携带 usage;最终以 data: [DONE] 结束。
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{"content":"你好"},"finish_reason":null}]}
...
data: {"id":"cmpl-xxx","object":"chat.completion.chunk","created":1698999575,"model":"kimi-k2.6","choices":[{"index":0,"delta":{},"finish_reason":"stop","usage":{"prompt_tokens":19,"completion_tokens":13,"total_tokens":32}}]}
data: [DONE]
将 {BASE} 换为你的站点根(示例 https://www.libav.cn)。
| 端点 | 方法 | 说明 |
|---|---|---|
| /v1/chat/completions / /api/v1/chat/completions | POST | 对话补全(OpenAI 兼容) |
| /api/v1/chat/listmodel | GET | 查询可用模型(按 type 分组) |
| /api/v1/files | POST / GET | 上传与列出文件 |
| /api/v1/files/{file_id} | GET / DELETE / PATCH | 文件详情、删除、更新(上游支持时) |
| /api/v1/files/{file_id}/content | GET | 获取文件原始内容 |
当前网关返回 OpenAI 兼容错误体:{ "error": { "message", "type", "code" } }。建议同时记录 HTTP 状态码、error.code 与 X-Trace-Id。
覆盖 /v1/chat/completions 等 Chat 兼容接口的高频错误。
| 矩阵 key | 状态码 | error.code | error.type | 默认 message |
|---|---|---|---|---|
| INVALID_API_KEY_FORMAT | 401 | invalid_api_key | invalid_request_error | 本接口仅支持 Secret Key:Authorization: Bearer sk-...(或旧版 sk_...) |
| INVALID_API_KEY | 401 | invalid_api_key | invalid_request_error | 无效的 Secret Key |
| OPENAPI_SK_SERVICE_UNAVAILABLE | 503 | server_error | api_error | OpenAPI 密钥服务不可用 |
| INVALID_REQUEST_MESSAGES_REQUIRED | 400 | invalid_request_error | invalid_request_error | 请求体需包含 messages(非空数组) |
| MODEL_NOT_FOUND | 400 | model_not_found | invalid_request_error | - |
| CONTEXT_LENGTH_EXCEEDED | 400 | context_length_exceeded | invalid_request_error | - |
| INSUFFICIENT_QUOTA | 402 | insufficient_quota | invalid_request_error | 配额不足或者当前套餐不包含该模型,请先充值 |
| RATE_LIMIT_EXCEEDED | 429 | rate_limit_exceeded | rate_limit_error | 请求过于频繁,请稍后再试 |
| INTERNAL_SERVER_ERROR | 500 | server_error | api_error | - |
覆盖文件上传、查询、删除、内容读取等接口。
| 矩阵 key | 状态码 | error.code | error.type | 默认 message |
|---|---|---|---|---|
| INVALID_API_KEY_FORMAT | 401 | invalid_api_key | invalid_request_error | 本接口仅支持 Secret Key:Authorization: Bearer sk-...(或旧版 sk_...) |
| INVALID_API_KEY | 401 | invalid_api_key | invalid_request_error | 无效的 Secret Key |
| OPENAPI_SK_SERVICE_UNAVAILABLE | 503 | server_error | api_error | OpenAPI 密钥服务不可用 |
| FILES_PROVIDER_NOT_SUPPORTED | 400 | invalid_request_error | invalid_request_error | - |
| FILES_PROVIDER_API_KEY_MISSING | 503 | server_error | api_error | - |
| FILES_METHOD_NOT_ALLOWED | 405 | invalid_request_error | invalid_request_error | - |
| FILES_MULTIPART_REQUIRED | 400 | invalid_request_error | invalid_request_error | Content-Type 必须为 multipart/form-data |
| INTERNAL_SERVER_ERROR | 500 | server_error | api_error | - |
覆盖模型列表查询接口。
| 矩阵 key | 状态码 | error.code | error.type | 默认 message |
|---|---|---|---|---|
| INVALID_API_KEY_FORMAT | 401 | invalid_api_key | invalid_request_error | 本接口仅支持 Secret Key:Authorization: Bearer sk-...(或旧版 sk_...) |
| INVALID_API_KEY | 401 | invalid_api_key | invalid_request_error | 无效的 Secret Key |
| OPENAPI_SK_SERVICE_UNAVAILABLE | 503 | server_error | api_error | OpenAPI 密钥服务不可用 |
| INTERNAL_SERVER_ERROR | 500 | server_error | api_error | - |
以下适用于「OpenAI 兼容」类设置:把**接口根**指到河图,把 **API Key** 填成个人中心签发的 **SK**(sk- 或 sk_ 开头)。不要在末尾多写 /chat/completions,由客户端自动拼接。
Cursor 各版本文案可能略有差异;核心是「Base URL 指向 …/api/v1 + Key 为 SK」。
以 Continue 为例,在配置文件中加入自定义模型(路径因版本而异,常见为项目内 .continue/config.json 或用户目录下 Continue 配置):
| 字段 | 说明 |
|---|---|
| apiBase | https://www.libav.cn/api/v1 |
| apiKey | 河图 SK(sk-...) |
| model | 与账号可用模型一致,例如 kimi-k2.5(以 listmodel / 个人中心为准,也可以直接使用Hetu,通过系统进行优选) |
{
"models": [
{
"title": "河图",
"provider": "hetu",
"model": "Hetu",
"apiKey": "sk-请替换为个人中心复制的密钥",
"apiBase": "https://www.libav.cn/api/v1"
}
]
}
其它宣称「兼容 OpenAI API」的 VS Code 扩展,一般同样填写 Base URL = https://www.libav.cn/api/v1、API Key = SK 即可。
需设置 HETU_SK;HETU_BASE 为站点根(示例 https://www.libav.cn)。cURL 可先 export BASE=https://www.libav.cn。Python OpenAI SDK 的 base_url 须为 {BASE}/api/v1(见上文「OpenAI 官方 SDK 与 base_url」)。
SYS_PROMPT='你是一位资深软件工程师,擅长:编写清晰可维护代码、遵循最佳实践、提供必要注释、考虑边界与性能。输出要求:先给3-6条思路,再给完整可运行代码,最后说明风险与权衡。避免重复表达。'
curl "${BASE}/api/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${HETU_SK}" \
-H "X-Trace-Id: $(uuidgen)" \
-d '{
"model": "kimi-k2.5",
"temperature": 1.0,
"top_p": 0.95,
"max_tokens": 4096,
"thinking": {"type": "enabled"},
"messages": [
{"role": "system", "content": "'"${SYS_PROMPT}"'"},
{"role": "user", "content": "请帮我实现 xxx ..."}
]
}'
// Node 18+(内置 fetch)。保存为 mjs 或 package.json 中 "type":"module"
(async () => {
const BASE = (process.env.HETU_BASE || "https://www.libav.cn/").replace(/\/$/, "");
const sk = process.env.HETU_SK;
const systemPrompt = `你是一位资深软件工程师,擅长:
- 编写清晰、可维护的代码
- 遵循最佳实践和设计模式
- 提供必要且简洁的注释
- 考虑性能、错误处理和边界条件
输出要求:
1) 先用 3-6 条要点说明方案
2) 给出完整可运行代码
3) 解释关键逻辑、风险点与权衡
4) 避免重复表达`;
const res = await fetch(`${BASE}/api/v1/chat/completions`, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${sk}`,
"X-Trace-Id": crypto.randomUUID(),
},
body: JSON.stringify({
model: "kimi-k2.5",
temperature: 1.0,
top_p: 0.95,
max_tokens: 4096,
thinking: { type: "enabled" },
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: "请帮我实现 xxx ..." },
],
}),
});
console.log(await res.json());
})();
import os
from openai import OpenAI
_base = os.environ["HETU_BASE"].rstrip("/")
client = OpenAI(
api_key=os.environ["HETU_SK"],
base_url=_base + "/api/v1",
)
SYSTEM_PROMPT = """你是一位资深软件工程师,擅长:
- 编写清晰、可维护的代码
- 遵循最佳实践和设计模式
- 提供必要且简洁的注释
- 考虑性能、错误处理和边界条件
输出要求:
1) 先用 3-6 条要点说明方案
2) 给出完整可运行代码
3) 解释关键逻辑、风险点与权衡
4) 避免重复表达
"""
completion = client.chat.completions.create(
model="kimi-k2.5",
temperature=1.0,
top_p=0.95,
max_tokens=4096,
extra_body={"thinking": {"type": "enabled"}},
extra_headers={"X-Trace-Id": os.urandom(8).hex()},
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": "请帮我实现 xxx ..."},
],
)
print(completion.choices[0].message.content)
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
base := strings.TrimSuffix(os.Getenv("HETU_BASE"), "/")
sk := os.Getenv("HETU_SK")
systemPrompt := "你是一位资深软件工程师。输出要求:先给3-6条思路,再给完整可运行代码,并解释关键逻辑与风险;避免重复表达。"
payload := map[string]any{
"model": "kimi-k2.5",
"temperature": 1.0,
"top_p": 0.95,
"max_tokens": 4096,
"thinking": map[string]any{"type": "enabled"},
"messages": []map[string]any{
{"role": "system", "content": systemPrompt},
{"role": "user", "content": "请帮我实现 xxx ..."},
},
}
b, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", base+"/api/v1/chat/completions", bytes.NewReader(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+sk)
req.Header.Set("X-Trace-Id", fmt.Sprintf("go-%d", os.Getpid()))
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}
返回结构与 OpenAI 兼容:`choices[0].message.content` 为模型正文。
{
"id": "chatcmpl-5ad321c8-4bf8-4602-979d-ed63d578b7cd",
"object": "chat.completion",
"created": 1774277750,
"model": "kimi-k2.5",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "你好!在基础数学中:\\n\\n**1 + 1 = 2**"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 32,
"completion_tokens": 300,
"total_tokens": 332
}
}
无可用模型时返回 400,code: no_available_model。
curl "${BASE}/api/v1/chat/completions" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${HETU_SK}" \
-d '{"model":"Auto","messages":[{"role":"user","content":"你好"}]}'
(async () => {
const BASE = (process.env.HETU_BASE || "https://www.libav.cn/").replace(/\/$/, "");
const sk = process.env.HETU_SK;
const res = await fetch(`${BASE}/api/v1/chat/completions`, {
method: "POST",
headers: { "Content-Type": "application/json", Authorization: `Bearer ${sk}` },
body: JSON.stringify({ model: "Auto", messages: [{ role: "user", content: "你好" }] }),
});
console.log(await res.json());
})();
import os
from openai import OpenAI
_base = os.environ["HETU_BASE"].rstrip("/")
client = OpenAI(
api_key=os.environ["HETU_SK"],
base_url=_base + "/api/v1",
)
completion = client.chat.completions.create(
model="Auto",
messages=[{"role": "user", "content": "你好"}],
)
print(completion.choices[0].message.content)
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
base := strings.TrimSuffix(os.Getenv("HETU_BASE"), "/")
sk := os.Getenv("HETU_SK")
payload := map[string]any{
"model": "Auto",
"messages": []map[string]string{{"role": "user", "content": "你好"}},
}
b, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", base+"/api/v1/chat/completions", bytes.NewReader(b))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+sk)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}
示例统一使用 /api/v1/chat/listmodel;亦可用 /v1/chat/listmodel(与网关逻辑一致)。
curl -sS "${BASE}/api/v1/chat/listmodel" \
-H "Authorization: Bearer ${HETU_SK}"
(async () => {
const BASE = (process.env.HETU_BASE || "https://www.libav.cn/").replace(/\/$/, "");
const sk = process.env.HETU_SK;
const r = await fetch(`${BASE}/api/v1/chat/listmodel`, {
headers: { Authorization: `Bearer ${sk}` },
});
console.log(await r.json());
})();
import json
import os
from urllib.request import Request, urlopen
base = os.environ["HETU_BASE"].rstrip("/")
req = Request(
f"{base}/api/v1/chat/listmodel",
headers={"Authorization": f"Bearer {os.environ['HETU_SK']}"},
)
with urlopen(req) as resp:
print(json.loads(resp.read().decode()))
package main
import (
"fmt"
"io"
"net/http"
"os"
"strings"
)
func main() {
base := strings.TrimSuffix(os.Getenv("HETU_BASE"), "/")
sk := os.Getenv("HETU_SK")
req, _ := http.NewRequest("GET", base+"/api/v1/chat/listmodel", nil)
req.Header.Set("Authorization", "Bearer "+sk)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}
按资源类型分组返回数组;若无配额/无可用模型则返回空数组 []。
[
{
"type": "text",
"models": [
"kimi-k2.5",
"qwen3.5"
]
},
{
"type": "image",
"models": [
"qwen-image-plus"
]
}
]
SK 仅用于服务端调用 Chat / listModel(如 /api/v1/chat/completions、/api/v1/chat/listmodel),勿写入前端页面或公开仓库。不要在日志中打印完整 SK。