Keural API
使用 API 密钥发送 OpenAI Chat Completions 格式的请求。
以 OpenAI Chat Completions 格式调用 Keural 中已登记的模型。
Base URL 的格式为 https://<各环境的公开 API 域名>/llm/v1。公开 API 域名因环境而异,请向管理员确认。
| 方法 | 路径 | 说明 |
|---|---|---|
POST | /llm/v1/chat/completions | 创建对话(支持流式传输) |
GET | /llm/v1/models | 与密钥关联的模型列表 |
GET | /llm/v1/models/{model} | 与密钥关联的模型信息 |
不支持嵌入、图像生成、语音和 Responses API 路径,发送到这些路径将返回 404。
使用流程
| 步骤 | 操作 |
|---|---|
| 1. 签发密钥 | 在 设置 → API 中选择模型并获取密钥。复制模型 ID 和密钥。 |
| 2. 连接客户端 | 在应用或代码中填入 Base URL、API 密钥和模型 ID。 |
| 3. 使用与管理 | 在同一界面查看用量,并根据需要重新签发或撤销密钥。 |
准备事项
| 项目 | 内容 |
|---|---|
| Keural 账户 | 可登录的账户 |
| API 菜单 | 若设置中没有 API 菜单,请向管理员申请启用该功能。 |
| 组织成员权限 | 要在组织工作区获取密钥,组织管理员需先允许您使用 API。参见 组织成员的 API 权限。 |
| Base URL | 管理员提供的公开 API 地址 |
| 客户端 | 支持 OpenAI API 兼容连接的应用或 SDK |
签发 API 密钥
- 在账户菜单中打开 设置 → API。在桌面应用和移动应用中,它位于 工具 区域。
- 在 API keys 标签页中,选择密钥的归属(个人工作区或组织工作区)以及 Model ID。
- 如有需要,设定 New key expiration (optional, Korea time)。留空则在撤销前一直有效。
- 点击 Issue key,然后用 Copy key 复制密钥并妥善保管。完整密钥仅在此时显示一次。
- 密钥与所选工作区及一个模型相关联。用量归属于签发密钥的人。
- 同一工作区、同一模型只能有一个密钥。需要新密钥时,请重新签发或撤销现有密钥。
- 丢失密钥后将无法再次查看,请重新签发。重新签发后,之前的密钥立即失效。
- 若没有可签发的模型,请向管理员确认模型的公开设置、套餐和组织 API 权限。
组织成员的 API 权限
仅适用于组织所有者和管理员。要让成员在组织工作区中获取密钥,管理员需先行允许。所有成员的默认值为阻止。
组织管理 → Organization API 由以下三个区域组成。若没有该菜单,说明 API 功能已关闭,或该账户没有组织管理权限。
| 区域 | 作用 |
|---|---|
| API permissions by user | 为每位成员开启或关闭 API 使用权限。 |
| Issued keys | 查看组织中签发的密钥状态并撤销。无法查看密钥全文。 |
| API usage | 查看组织中签发的密钥的请求数和令牌用量。 |
| 操作 | 结果 |
|---|---|
| 开启权限 | 该成员可以在组织工作区中签发密钥。 |
| 关闭权限 | 阻止新签发以及使用现有密钥的调用。已签发的密钥不会自动删除,需要时请在 Issued keys 中撤销。 |
成员退出或被移出组织时,该成员在组织中获得的密钥会自动撤销。
连接到客户端
在兼容 OpenAI API 的应用(聊天客户端、IDE 扩展、自动化工具等)中输入以下三项。
| 项目 | 输入内容 | 应用中的项目名称 |
|---|---|---|
| Base URL | 管理员提供的公开 API 地址(…/llm/v1) | Base URL、API Base、Endpoint、Host |
| API Key | 已获得的密钥(前后不要有空格) | API Key、Token、Secret Key、Authorization |
| Model | 签发界面中的 Model ID。必须与密钥关联的模型完全一致 | Model、Model ID、Model Name |
- 在应用设置中添加 OpenAI 兼容连接(Connection)。
- 输入 Base URL 和 API Key,然后保存。
- 从模型列表中选择模型。列表中仅显示与密钥关联的一个模型。
- 发送一条简短消息,确认是否收到回复。
请求格式如下。
| 类别 | 内容 |
|---|---|
| 对话请求 | POST <Base URL>/chat/completions |
| 模型查询 | GET <Base URL>/models |
| 认证标头 | Authorization: Bearer <已签发的密钥> |
| 内容标头 | Content-Type: application/json |
第一个请求
export KEURAL_API_KEY='your_issued_key'
export KEURAL_BASE_URL='https://<各环境的公开 API 域名>/llm/v1'
export MODEL_ID='签发界面中的模型 ID'
curl "$KEURAL_BASE_URL/chat/completions" \
-H "Authorization: Bearer $KEURAL_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"model\":\"$MODEL_ID\",\"messages\":[{\"role\":\"user\",\"content\":\"你好。\"}]}"请求正文中的 model 必须与密钥关联的模型 ID 一致。若前面带有 provider/模型ID 这样的路径,则比较最后一个 / 之后的部分。不一致时返回 403。响应中的 model 始终包含密钥的模型 ID。
from openai import OpenAI
import os
client = OpenAI(
api_key=os.environ["KEURAL_API_KEY"],
base_url=os.environ["KEURAL_BASE_URL"],
)
res = client.chat.completions.create(
model=os.environ["MODEL_ID"],
messages=[{"role": "user", "content": "你好。"}],
)
print(res.choices[0].message.content)支持的请求字段
仅接受以下 18 个顶层字段。发送其他字段将返回 400。值为 null 的可选字段按未发送处理。
| 字段 | 规则 |
|---|---|
model | 必填。密钥的模型 ID |
messages | 必填。1 到 4,096 项 |
stream · stream_options | 仅当 stream: true 时发送 stream_options。支持 include_usage。 |
tools | 最多 128 个。函数名为 [A-Za-z0-9_-],1 到 64 个字符 |
tool_choice | none · auto · required · 指定函数。required 需要存在 tools。 |
parallel_tool_calls | 模型不支持时返回 400 |
response_format | text · json_object · json_schema |
max_tokens · max_completion_tokens | 二者只发送其一。若都不发送,则为 4,096(若模型上限更低则为该值)。超过模型上限返回 400。 |
temperature | 0 到 2。模型不支持时返回 400 |
top_p | 0 到 1 |
frequency_penalty · presence_penalty | -2 到 2 |
stop | 字符串或最多 4 项的数组 |
seed | 整数 |
user | 最多 256 个字符 |
n | 仅 1 |
消息
| 角色 | 接受的字段 |
|---|---|
system · developer | content、name |
user | content(字符串,或文本和图像片段的数组)、name |
assistant | content、name、refusal、tool_calls |
tool | content、tool_call_id |
tool消息对前面tool_calls中的每个id只回复一次。- 图像片段(
image_url)只能放在支持图像的模型的user消息中。可使用http或https地址,或 PNG、JPEG、GIF、WebP 的 base64 data URI。detail为auto、low或high。
正文
| 项目 | 限制 |
|---|---|
| Content-Type | application/json |
| 大小 | 1MiB |
| JSON 结构 | 一个顶层对象,嵌套深度不超过 64,不允许重复的键 |
| 请求时间 | 最长 600 秒 |
违反正文规则将返回 400,且 param 为 body。
流式传输
在请求中加入 "stream": true 后,将以 SSE 形式响应。数据块以 data: ... 事件发送,结束时发送 data: [DONE]。加入 "stream_options": {"include_usage": true} 后,在 [DONE] 之前会额外发送一个令牌用量数据块。
加入 include_usage 后,每个数据块都会包含 usage: null,最后一个用量数据块的 choices 为空数组。非流式响应只有在输入和输出令牌都已确认时才会包含 usage。
响应的 id 格式为 chatcmpl-<x-request-id>。所有响应标头都包含 x-request-id。
流式传输过程中出错时,将发送包含错误 JSON 的 data: 事件,然后在没有 [DONE] 的情况下结束连接。单个数据块超过 1MiB,或响应超过 16MiB,则以 503 结束。
curl -N "$KEURAL_BASE_URL/chat/completions" \
-H "Authorization: Bearer $KEURAL_API_KEY" \
-H 'Content-Type: application/json' \
-d "{\"model\":\"$MODEL_ID\",\"messages\":[{\"role\":\"user\",\"content\":\"你好。\"}],\"stream\":true,\"stream_options\":{\"include_usage\":true}}"使用限制
按用户、组织和模型分别限制并发请求数、每分钟请求数(RPM)和每分钟令牌数(TPM)。实际数值因环境而异。
每分钟令牌数在接收请求时预先扣除。输入按每 4 个英文字符计 1 个令牌,其他字符按每个字符计 1 个令牌,一张图像计 2,000 个令牌。输出按 max_tokens(最多 4,096)预先扣除,因此只设置所需的输出上限,可获得更多的限额余量。
429 code | 原因 | Retry-After |
|---|---|---|
rate_limit_exceeded | 超过 RPM、TPM 或并发请求数 | RPM·TPM 为 60 秒,并发请求为 1 秒 |
api_busy | 服务器处理能力已满 | 无。请稍后再试。 |
upstream_rate_limit | 模型供应商超出限制 | 无 |
密钥管理
在 设置 → API → API keys 标签页中可查看密钥状态(有效、已过期、已撤销),并进行重新签发或撤销。
密钥是以 krl_llm_ 开头的 51 个字符的字符串。每个密钥归属下只能有一个密钥,若已存在,则重新签发。有效期只能设定为今天之后的日期。
| 操作 | 结果 | 注意事项 |
|---|---|---|
| 重新签发 | 获得新密钥。 | 之前的密钥立即失效。已连接应用中的密钥也需一并更换。 |
| 撤销 | 立即阻止该密钥。 | 密钥可能泄露时使用。已撤销的密钥无法恢复。 |
查看用量
API 请求和令牌用量,可在以下两个位置查看。
| 位置 | 内容 |
|---|---|
| 设置 → API → API usage 标签页 | 当前工作区中您签发的密钥的用量 |
| 组织管理 → Organization API 下方的 API usage | 组织中签发的所有密钥的用量(组织所有者和管理员) |
查询条件
| 条件 | 说明 |
|---|---|
| 开始时间 · 结束时间 | 以韩国时间为准。包含开始时间,不包含结束时间。留空时为最近 7 天,每次最多查询 90 天。 |
| Model ID | 仅查询特定模型的请求。留空则查询全部。 |
| 请求状态 | 从 All · Running · Completed · Failed · Cancelled · Unknown 中选择。 |
设定条件后点击 Search。若要反映最近的请求,请点击 Refresh。
界面中显示的值
- Applied time range (KST):实际查询的时间范围。开始或结束时间留空,或超过 90 天时,将显示服务器调整后的时间范围。
- Requests 以及 Input tokens · Output tokens · Total tokens 的合计:仅合计已确认的值。未确认的令牌显示为 Unconfirmed。
- 请求列表:每个请求显示请求时间、Model ID、请求状态以及输入、输出、总令牌数。每页显示 20 条,通过 Previous 和 Next 翻页。
点击某行的 Request details 可显示以下值。
| 项目 | 说明 |
|---|---|
| 请求 ID | 咨询时提供的值 |
| 响应方式 | 流式或非流式响应 |
| 用量确认状态 | Confirmed · Partially confirmed · Unconfirmed |
| 结束时间 · 响应时间(ms) | 请求结束的时间和耗时 |
| 缓存读取 · 缓存创建 · 推理令牌 | 仅当模型返回这些值时显示 |
流式请求无需 stream_options.include_usage 也会记录用量。请求中途断开时,可能保留为 Partially confirmed 或 Unconfirmed。
错误格式
错误以 OpenAI 兼容格式返回。
{
"error": {
"message": "可供人阅读的错误说明",
"type": "authentication_error",
"code": "invalid_api_key",
"param": null
}
}type 由状态码决定,code 用于区分原因。
| 状态 | type | code | 原因 |
|---|---|---|---|
400 | invalid_request_error | invalid_request | 违反字段、值或正文规则。param 中为有问题的字段 |
400 | invalid_request_error | upstream_rejected_request | 模型供应商拒绝了请求 |
401 | authentication_error | invalid_api_key | 密钥格式错误、密钥缺失、已过期、已撤销或已重新签发,或 Authorization 标头不止一个 |
403 | permission_error | api_disabled | Keural API 功能已关闭 |
403 | permission_error | model_api_disabled | 该模型的 API 公开已关闭 |
403 | permission_error | model_not_allowed | model 与密钥的模型不同,或成员没有 API 权限 |
404 | invalid_request_error | not_found | 路径不存在 |
405 | invalid_request_error | method_not_allowed | 方法错误。允许的方法见 Allow 标头 |
429 | rate_limit_error | 参见上方 使用限制 表格 | 超过限制 |
503 | server_error | upstream_timeout | 600 秒内响应未结束 |
503 | server_error | invalid_upstream_response | 供应商响应格式异常,或流大小超限 |
503 | server_error | dependency_unavailable · unsupported_provider | 临时的内部问题。咨询时请附上 x-request-id |
故障排除
| 症状 | 响应码 | 需确认的项目 |
|---|---|---|
| 模型列表为空或连接失败 | 404 · 405 | Base URL 是否以 …/llm/v1 结尾 |
| 认证失败 | 401 | 密钥是否输入有误或前后有空格,是否已过期、撤销或重新签发 |
| 连接正常但无法使用模型 | 403 | 模型 ID 是否与密钥的模型一致,组织 API 权限 |
| 响应缓慢或偶尔失败 | 429 | 使用限制 |
| 长时间没有响应 | 5xx | 稍后重试 |
| 用量看不到或与实际不符 | — | 查询时间范围以及密钥所属的工作区 |
若问题仍未解决,请附上以下信息联系管理员。请勿发送密钥全文和提示词内容。
- 发生时间
- 使用的模型 ID
- 客户端应用的名称和版本
- 响应标头中的
x-request-id - 界面上显示的错误信息