摘要
- 始终在 OpenAI SDK 客户端中显式设置 base URL,以避免命中错误的端点。
- 仔细解析流式传输块,以从最后一个 SSE 事件中提取最终的令牌使用情况。
- 使用 response_format json_object 确保包装应用程序的结构化输出。
- 在发送大提示之前检查您的上下文窗口限制,以避免截断错误。
忘记为 OpenAI 客户端设置 Base URL
第一个错误发生在发送请求之前。当您从主要提供商切换到更便宜的替代方案时,您经常忘记更新基础 URL。您的 SDK 将请求发送到默认端点,该端点可能已关闭或受到速率限制。
立即配置你的客户端对象。将基础 URL 设置为 https://api.apillmcheapest.com/v1 在您的 SDK 初始化中。这确保所有调用都发送到正确的服务器。您可以使用任何标准的 OpenAI 兼容库。更改通常只需要一行代码。
- 使用新的基础 URL 初始化客户端。
- 通过简单的模型列表调用验证连通性。
- 检查 API 密钥是否正确传递。
from openai import OpenAI
client = OpenAI(base_url="https://api.apillmcheapest.com/v1", api_key="YOUR_KEY")
resp = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Summarise this thread without softening it."}],
)
print(resp.choices[0].message.content)这一步骤可防止数小时的调试工作。您希望您的包装应用程序从一开始就能可靠运行。
配置流式响应块
流式传输对于用户体验至关重要,但它引入了复杂性。许多开发者将流式传输响应视为标准 JSON。他们尝试将整个流解析为单个对象。这会失败,因为数据是分片到达的。
单独处理每个数据块。累积每个事件中的文本内容。仅在流结束时解析组合后的最终字符串。这种方法适用于您选择的任何 LLM API。它使您的代码保持简单和健壮。
- 监听
contentfield in each chunk. - 将文本附加到缓冲区变量。
- 仅在流关闭后处理完整文本。
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Tell the story in second person."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)流式传输显著降低了感知延迟。用户会看到 token 实时出现。这让你的应用感觉更快、响应更灵敏。
忽略结构化数据的 JSON 模式
如果您正在构建 AI 包装器,您可能需要结构化数据。要求模型返回 JSON 但不强制执行格式会导致解析器出错。模型可能会添加 markdown 代码块或额外文本。这会破坏您的下游逻辑。
使用 response_format 参数。将其设置为 {"type": "json_object"}. 这强制模型输出有效的 JSON。它减少了解析错误并简化了您的代码。每次都能获得一致的结果。
- 为您的需求定义严格的 JSON 架构。
- 在请求中设置响应格式参数。
- 在进一步处理之前验证输出。
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.apillmcheapest.com/v1", apiKey: process.env.API_KEY });
const resp = await client.chat.completions.create({
model: "uncensored",
messages: [{ role: "user", content: "Draft a villain monologue for my game." }],
});
console.log(resp.choices[0].message.content);此功能对于数据提取任务至关重要。它确保您的小型项目能够处理数千次请求而无需人工干预。
在不检查上下文窗口的情况下触及 Token 限制
上下文窗口有硬性限制。如果您发送的提示超出模型容量,请求将失败。您白白损失 token 和金钱。许多开发人员假设限制比实际更高。
发送数据前检查上下文窗口大小。我们的模型总共支持 100,000 个 token。这包括输入和输出。将提示保持在 84,000 token 以下以留出生成空间。准确计算 token 数量。使用 tokenizer 库以确保精度。
- 计算提示文本中的令牌。
- 为响应添加预估令牌数。
- 远低于 100,000 的限制。
curl https://api.apillmcheapest.com/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [{"role": "user", "content": "What is the current status of the database migration job?"}]
}'忽略限制会导致昂贵的错误。您希望最大化每次 API 调用的价值。请仔细规划上下文使用。
假设函数调用像 GPT-4 一样工作
不同提供商的函数调用语法各不相同。工具定义格式可能略有差异。您的代码可能会发送模型无法识别的参数。这会导致工具调用为空或出现错误。
查阅你特定 API 的函数调用文档。使用标准 JSON 模式格式定义工具。在请求体中传递 tools 数组。模型在响应中返回工具调用。执行函数并返回结果。
- 使用清晰的描述定义工具。
- 在请求中传入 tools 数组。
- 在代码循环中处理工具调用。
from openai import OpenAI
client = OpenAI(base_url="https://api.apillmcheapest.com/v1", api_key="YOUR_KEY")
resp = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Summarise this thread without softening it."}],
)
print(resp.choices[0].message.content)函数调用支持复杂的工作流。它允许模型决定何时使用外部数据。确保您的实现符合 API 规范。
忽略 SSE 中的流式传输令牌计数
Token 计数对于计费至关重要。您需要确切知道自己花费了多少。一些 API 仅在最终响应中返回 Token 使用情况。其他 API 则在每个块中包含它。您需要知道在哪里找到数据。
检查流的最后一个分块。Token 用量通常包含在最后一个 SSE 事件中。解析此数据以跟踪您的支出。将输入和输出 token 相加以获得总成本。这有助于您控制预算。
- 监听流中的最后一个块。
- 提取
usage来自响应的数据。 - 记录令牌计数以进行计费分析。
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Tell the story in second person."}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)精准追踪可避免意外账单。您可以根据令牌使用情况优化提示词。这对扩展您的项目至关重要。
未使用 Seed 获得可重现结果
LLM 默认是非确定性的。运行相同的提示两次可能会产生不同的输出。这对于创意任务来说没问题,但对于测试来说则不好。您需要一致的结果来调试代码。
设置 seed 参数到您的请求中。使用固定的整数值。这增加了获得相同输出的可能性。它不能保证 100% 的确定性。它使测试变得更加容易。
- 为您的种子选择一个随机整数。
- 在每个请求中包含 seed。
- 验证开发期间的输出一致性。
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.apillmcheapest.com/v1", apiKey: process.env.API_KEY });
const resp = await client.chat.completions.create({
model: "uncensored",
messages: [{ role: "user", content: "Draft a villain monologue for my game." }],
});
console.log(resp.choices[0].message.content);可重复性显著加快了调试速度。您可以精确定位问题,无需猜测。在开发期间使用种子,并在生产环境中移除它们。
不检查限制条件选择最便宜的 LLM API
令牌单价只是故事的一部分。速率限制同样重要。如果你达到限制,你的应用就会停止工作。你可能会为重试或用户流失支付更多费用。请比较不同提供商的限制。
检查每分钟请求数和并发连接数。我们的 API 允许每分钟 300 次请求。这足以满足大多数小型项目。确保限制与您的使用模式匹配。避免限制严格的提供商。
- 跨提供商比较 RPM 限制。
- 检查并发请求限制。
- 使用小规模负载测试测试限制。
curl https://api.apillmcheapest.com/v1/chat/completions \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "uncensored",
"messages": [{"role": "user", "content": "What is the current status of the database migration job?"}]
}'最便宜的选项未必是最佳选择,如果它拖慢了速度。请在成本与性能之间取得平衡。您的用户期望快速的响应。