AI 调用文档
这是一个 OpenAI 兼容的 AI 接口。你可以像调用 OpenAI 一样,把 base_url 换成我们的地址,就能在自己的程序、脚本或应用里使用它。
支持流式输出、多模型切换,中文表现良好。接口已开启 CORS,浏览器可以直接调用。
本服务由个人搭建并维护,不保证 100% 可用。请勿用于关键生产链路,也请勿滥用。
快速开始
三步就能跑起来:
- 拿到接口地址
https://ai.lelegame.dpdns.org/v1 - 用任意 OpenAI 兼容客户端 / 库官方 SDK、第三方客户端、curl 都可以。
- 填地址 + 模型名
fast立刻就能对话。
如果你用 OpenAI 官方 SDK,只需要把 base_url 改成 https://ai.lelegame.dpdns.org/v1,其余代码一行都不用动。
接口地址
| 用途 | 地址 |
|---|---|
| Base URL | https://ai.lelegame.dpdns.org/v1 |
| Chat Completions | https://ai.lelegame.dpdns.org/v1/chat/completions |
| 模型列表 | https://ai.lelegame.dpdns.org/v1/models |
鉴权
当前无需 API Key。直接请求即可,不需要在 Header 里带 Authorization。
很多客户端和 SDK 会强制要求填写 Key,随便填一个非空字符串即可,例如 ollama、sk-xxx、123。
未来可能会加入 API Key 校验,届时会在本页公告。请定期回来看一眼。
模型列表
通过 GET /v1/models 获取当前可用的模型。
curl https://ai.lelegame.dpdns.org/v1/models{
"object": "list",
"data": [
{ "id": "fast", "object": "model", "created": 1712345678, "owned_by": "local" },
{ "id": "3b", "object": "model", "created": 1712345678, "owned_by": "local" }
]
}注意事项
- 模型名区分大小写,必须和列表里的
id完全一致。 - 模型列表可能随服务端配置变化,调用前建议先请求一次
/v1/models。
请求格式
POST /v1/chat/completions Header:Content-Type: application/json
请求体字段
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
model | string | 是 | 模型名,例如 fast |
messages | array | 是 | 对话历史,每条包含 role 和 content |
stream | boolean | 否 | 是否流式返回,默认 false |
temperature | number | 否 | 0 ~ 2,默认 0.7 |
max_tokens | integer | 否 | 最大生成长度 |
完整请求体示例
{
"model": "fast",
"messages": [
{ "role": "system", "content": "你是一个乐于助人的中文助手,回答尽量简洁。" },
{ "role": "user", "content": "用一句话解释什么是 API。" }
],
"stream": false,
"temperature": 0.7,
"max_tokens": 512
}响应格式
当 stream 为 false(默认)时,服务端一次性返回完整的 JSON。
响应字段说明
| 字段 | 说明 |
|---|---|
id | 本次请求的唯一 ID |
object | 固定为 chat.completion |
created | Unix 时间戳(秒) |
model | 实际使用的模型名 |
choices[0].message.content | AI 回复的正文 |
choices[0].finish_reason | 结束原因,通常为 stop |
usage | token 统计 |
完整响应示例
{
"id": "chatcmpl-8f3a1c2b9d4e",
"object": "chat.completion",
"created": 1712345678,
"model": "fast",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "API 就是程序之间约定好的一套调用接口。"
},
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 32, "completion_tokens": 48, "total_tokens": 80 }
}流式输出
把 stream 设为 true 后,服务端会以 SSE(Server-Sent Events)格式逐块返回内容:
- 每一行以
data:开头,后面跟一个 JSON 对象; - 每个 JSON 里,文本片段在
choices[0].delta.content; - 流的最后一行是
data: [DONE]。
data: {"id":"chatcmpl-8f3a1c2b9d4e","choices":[{"index":0,"delta":{"role":"assistant","content":""},"finish_reason":null}]}
data: {"id":"chatcmpl-8f3a1c2b9d4e","choices":[{"index":0,"delta":{"content":"API"},"finish_reason":null}]}
data: {"id":"chatcmpl-8f3a1c2b9d4e","choices":[{"index":0,"delta":{"content":" 就是"},"finish_reason":null}]}
data: {"id":"chatcmpl-8f3a1c2b9d4e","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]解析流时必须处理「不完整的行」。把每次读到的内容追加到一个 buffer 字符串,按 \n 切分,把最后一段留在 buffer 里,等下次数据到达再拼接。
代码示例
点击右上角标签切换语言,直接复制即可运行。通用参数:请求地址 https://ai.lelegame.dpdns.org/v1/chat/completions,模型名 fast,API Key 随意填非空字符串。
# 非流式
curl https://ai.lelegame.dpdns.org/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "fast",
"messages": [
{"role": "user", "content": "用一句话解释什么是 API"}
],
"stream": false
}'
# 流式(加 -N 关闭缓冲,才能逐块看到输出)
curl -N https://ai.lelegame.dpdns.org/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "fast",
"messages": [
{"role": "user", "content": "写一首关于秋天的短诗"}
],
"stream": true
}'# pip install openai
from openai import OpenAI
client = OpenAI(
base_url="https://ai.lelegame.dpdns.org/v1",
api_key="ollama", # 服务端当前不校验
)
# 非流式
resp = client.chat.completions.create(
model="fast",
messages=[
{"role": "system", "content": "你是一个乐于助人的中文助手。"},
{"role": "user", "content": "用一句话解释什么是 API。"},
],
)
print(resp.choices[0].message.content)
# 流式
stream = client.chat.completions.create(
model="fast",
messages=[{"role": "user", "content": "写一首关于秋天的短诗"}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content
if delta:
print(delta, end="", flush=True)
print()# pip install requests
import json
import requests
URL = "https://ai.lelegame.dpdns.org/v1/chat/completions"
payload = {
"model": "fast",
"messages": [{"role": "user", "content": "写一首关于秋天的短诗"}],
"stream": True,
}
headers = {"Content-Type": "application/json"}
with requests.post(URL, json=payload, headers=headers,
stream=True, timeout=120) as r:
r.raise_for_status()
for raw in r.iter_lines(decode_unicode=True):
if not raw:
continue
if not raw.startswith("data: "):
continue
data = raw[6:].strip()
if data == "[DONE]":
break
chunk = json.loads(data)
delta = chunk["choices"][0]["delta"].get("content")
if delta:
print(delta, end="", flush=True)
print()// Node.js 18+,保存为 stream.mjs 后运行:node stream.mjs
const URL = "https://ai.lelegame.dpdns.org/v1/chat/completions";
const res = await fetch(URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "fast",
messages: [{ role: "user", content: "写一首关于秋天的短诗" }],
stream: true,
}),
});
if (!res.ok) throw new Error("HTTP " + res.status);
const reader = res.body.getReader();
const decoder = new TextDecoder("utf-8");
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop();
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed.startsWith("data:")) continue;
const data = trimmed.slice(5).trim();
if (data === "[DONE]") {
process.stdout.write("\n");
process.exit(0);
}
const chunk = JSON.parse(data);
const delta = chunk.choices?.[0]?.delta?.content;
if (delta) process.stdout.write(delta);
}
}<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>流式对话 Demo</title>
</head>
<body>
<pre id="out" style="white-space:pre-wrap;font-family:sans-serif"></pre>
<script>
const out = document.getElementById("out");
async function chat(prompt) {
const res = await fetch("https://ai.lelegame.dpdns.org/v1/chat/completions", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "fast",
messages: [{ role: "user", content: prompt }],
stream: true,
}),
});
if (!res.ok) throw new Error("HTTP " + res.status);
const reader = res.body.getReader();
const decoder = new TextDecoder("utf-8");
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop();
for (const line of lines) {
const trimmed = line.trim();
if (!trimmed.startsWith("data:")) continue;
const data = trimmed.slice(5).trim();
if (data === "[DONE]") return;
const chunk = JSON.parse(data);
const delta = chunk.choices?.[0]?.delta?.content;
if (delta) out.textContent += delta;
}
}
}
chat("写一首关于秋天的短诗");
</script>
</body>
</html>package main
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"net/http"
"strings"
)
func main() {
url := "https://ai.lelegame.dpdns.org/v1/chat/completions"
body := map[string]any{
"model": "fast",
"stream": true,
"messages": []map[string]string{
{"role": "user", "content": "写一首关于秋天的短诗"},
},
}
buf, _ := json.Marshal(body)
req, _ := http.NewRequest("POST", url, bytes.NewReader(buf))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
scanner := bufio.NewScanner(resp.Body)
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if !strings.HasPrefix(line, "data:") {
continue
}
data := strings.TrimSpace(strings.TrimPrefix(line, "data:"))
if data == "[DONE]" {
break
}
var chunk struct {
Choices []struct {
Delta struct {
Content string `json:"content"`
} `json:"delta"`
} `json:"choices"`
}
if err := json.Unmarshal([]byte(data), &chunk); err != nil {
continue
}
if len(chunk.Choices) > 0 {
fmt.Print(chunk.Choices[0].Delta.Content)
}
}
fmt.Println()
}<?php
$url = "https://ai.lelegame.dpdns.org/v1/chat/completions";
$payload = json_encode([
"model" => "fast",
"messages" => [
["role" => "user", "content" => "用一句话解释什么是 API"],
],
"stream" => false,
], JSON_UNESCAPED_UNICODE);
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $payload,
CURLOPT_HTTPHEADER => ["Content-Type: application/json"],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 120,
]);
$res = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($code !== 200) {
exit("请求失败,HTTP " . $code . "\n" . $res);
}
$data = json_decode($res, true);
echo $data["choices"][0]["message"]["content"] ?? "解析失败";import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class ChatDemo {
public static void main(String[] args) throws Exception {
String body = """
{
"model": "fast",
"messages": [
{"role": "user", "content": "用一句话解释什么是 API"}
],
"stream": false
}
""";
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://ai.lelegame.dpdns.org/v1/chat/completions"))
.header("Content-Type", "application/json")
.timeout(Duration.ofSeconds(120))
.POST(HttpRequest.BodyPublishers.ofString(body))
.build();
HttpResponse<String> resp = HttpClient.newHttpClient()
.send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
System.out.println(resp.body());
}
}错误码
| 状态码 | 含义 | 排查方向 |
|---|---|---|
| 200 | 成功 | — |
| 400 | 请求体格式错误 | 检查 JSON 是否合法、字段名与类型是否正确 |
| 401 | 未授权 | 未来加 Key 后可能出现 |
| 404 | 路径错误 | 确认 URL 是 /v1/chat/completions |
| 429 | 请求过多 | 降低频率,稍后重试 |
| 500 | 服务端错误 | 服务可能未启动,稍后重试 |
| 502 / 503 | 网关错误 | 服务端离线或隧道中断 |
| 504 | 超时 | 改用流式或缩短输入 |
常见问题
为什么有时候回复很慢?
为什么偶尔出现 502?
支持并发请求吗?
支持上传文件或图片吗?
能用 OpenAI 官方 SDK 吗?
base_url 改为 https://ai.lelegame.dpdns.org/v1 即可。有没有 API Key?
浏览器直接调用会跨域失败吗?
fetch 调用。限制与注意事项
不要滥用。这是个人搭建的免费服务,请勿高并发刷接口、批量跑数据或做压力测试。
- 不要用于违法用途。
- 不要上传敏感信息。对话内容会被记录到服务端日志。
- 服务可能随时变动。接口地址、模型名、限流策略都可能调整。
- CORS 已开启。浏览器端可以直接调用。
- 超时建议。非流式请求建议客户端超时 60 秒以上;流式请求建议 120 秒左右。
- 并发限制为 1。请串行发送请求。