Felo API Platform 还提供 OpenAI 兼容接口(
https://openapi.felo.ai/api/v1)。用同一个 Key,现有的 OpenAI SDK 代码改一下 base_url 就能用。本篇先列出账号可用的模型,再按偏好顺序挑选一个,不在代码里写死模型名;同时把 Felo 非 OpenAI 格式的错误 body 整理成人能看懂的提示。
先看清成品
- 测试: pytest 1 项通过。
- 模拟服务器: 偏好列表里的模型不存在时,程序自动改用可用模型,并给出提示。
- 真实接口: 用无效 Key 调用,程序输出“✗ Felo 返回错误:HTTP 401 UNAUTHORIZED Invalid API Key”。
没有在 box 上跑的部分: box 上没有 Felo API Key。对真实接口只做过无效 Key 的调用:
/v2/chat和/api/v1/models都返回 HTTP 401,body 是{"status":401,"code":"UNAUTHORIZED","message":"Invalid API Key",…};不带 Key 时 message 是 "API Key is required"。其余部分在我写的模拟服务器fake_felo.py上运行,它按文档的结构返回固定的假内容。
合规提醒:
FELO_API_KEY只放在环境变量或服务器端,不要写进网页前端或提交到 Git。问题内容会发到 Felo 的服务器,不要提交个人隐私或公司机密。AI 回答引用网页时,版权归原作者:保留来源链接,引用前打开原文核对,不要整篇转载。检查链接时请求要少、要慢,并遵守对方网站的规则。计费规则以 Felo API Platform 的页面为准,本文不列价格。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
felo_models.py |
models.list() → 按 FELO_MODELS 的偏好顺序挑选 → 对话 → 显示 tokens;explain() 从错误 body 里取出 code 和 message |
test_models.py |
挑选逻辑 |
需要准备哪些环境?
| 项目 | 要求 | 说明 |
|---|---|---|
| Python | 3.9 以上 | pip install openai pytest |
| Felo | API Key | 文档中的地址:OpenAI 兼容 https://openapi.felo.ai/api/v1,Anthropic 兼容 https://openapi.felo.ai/api |
文件结构
46-felo-C-src/
├── felo_models.py
└── test_models.py
第 1 步:代码
felo_models.py:
"""用 Felo 的 OpenAI 兼容接口(base_url https://openapi.felo.ai/api/v1):先列出账号可用的模型,再按偏好顺序挑一个来对话。
模型名不写死:不同账号、不同时间可用的模型会变(文档的 Getting Started 也写了“如果账号里有就用较新的”)。
错误 body 不是 OpenAI 的格式,而是 {"status":401,"code":"UNAUTHORIZED","message":"..."}(实测),这里统一取出 code 和 message。
环境变量:FELO_API_KEY、FELO_OPENAI_BASE(默认 https://openapi.felo.ai/api/v1)、FELO_MODELS(偏好顺序,逗号分隔)
用法:python felo_models.py "问题" """
import os, sys
import openai
from openai import OpenAI
client = OpenAI(base_url=os.environ.get("FELO_OPENAI_BASE", "https://openapi.felo.ai/api/v1"),
api_key=os.environ.get("FELO_API_KEY") or "missing-key", max_retries=0)
def explain(e):
b = e.body if isinstance(getattr(e, "body", None), dict) else {}
b = b.get("error", b) if isinstance(b.get("error"), dict) else b
return f"HTTP {getattr(e, 'status_code', '?')} {b.get('code', '')} {b.get('message') or e}".strip()
def pick(available, prefer):
for m in prefer:
if m in available: return m
return None
def main():
prefer = [m.strip() for m in os.environ.get("FELO_MODELS", "").split(",") if m.strip()]
try:
available = [m.id for m in client.models.list()]
print("账号可用模型:" + "、".join(available))
model = pick(available, prefer) or available[0]
if prefer and model not in prefer: print(f"⚠ 偏好的模型 {prefer} 都不可用,改用 {model}")
r = client.chat.completions.create(model=model, messages=[{"role": "user", "content": sys.argv[1]}])
except openai.APIStatusError as e:
sys.exit(f"✗ Felo 返回错误:{explain(e)}")
print(f"[{model}] {r.choices[0].message.content}\n(tokens:输入 {r.usage.prompt_tokens} / 输出 {r.usage.completion_tokens})")
if __name__ == "__main__":
main()
第 2 步:运行
$ export FELO_API_KEY=...
$ FELO_MODELS=你想用的模型,备选模型 python felo_models.py "用一句话介绍电动牙刷"
# box 上(模拟服务器):
账号可用模型:fake-small、fake-large
[fake-large] (模拟)fake-large 收到:用一句话介绍电动牙刷
(tokens:输入 10 / 输出 8)
$ FELO_MODELS=not-exist python felo_models.py "你好"
账号可用模型:fake-small、fake-large
⚠ 偏好的模型 ['not-exist'] 都不可用,改用 fake-small
$ FELO_API_KEY=bad python felo_models.py "你好" # 真实接口
✗ Felo 返回错误:HTTP 401 UNAUTHORIZED Invalid API Key
调试示例
1. 写死的模型名。 示例代码里直接写了文档上提到的一个模型名。如果账号里没有这个模型,就会得到(模拟服务器上复现):
NotFoundError 404 {'message': 'model claude-sonnet-5 not found'}
文档本身也写了“如果账号里有就用较新的模型”,可见可用模型因账号而异。所以先 models.list() 列出来再挑选。
2. 错误信息不好读。 openai SDK 默认的报错是:
Error code: 401 - {'status': 401, 'code': 'UNAUTHORIZED', 'message': 'Invalid API Key', 'request_id': '…'}
这是真实接口的返回,Felo 的错误 body 不是 OpenAI 的 {"error": {...}} 格式。explain() 两种格式都能处理,只输出“HTTP 401 UNAUTHORIZED Invalid API Key”。另外设置了 max_retries=0,让 Key 错误立即暴露,不浪费时间重试。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| 404 model not found | 账号里没有这个模型 | 先列出可用模型 |
| 工具要求填 Anthropic 地址 | 例如 Claude Code | 按文档使用 https://openapi.felo.ai/api |
| 401 | Key 错误或没有带 Key | 检查环境变量 |
模板规则
- 模型名先查询再使用,不写死。
- 错误信息整理成 code 加 message。
- 改 base_url 之前,先确认要用的功能对方支持。
项目资源
| 用途 | 地址 |
|---|---|
| Felo API Platform 文档 | https://openapi.felo.ai/docs |
| Chat API(/v2/chat) | https://openapi.felo.ai/docs/api-reference/chat |
| 认证与限流 | https://openapi.felo.ai/docs/authentication |
| Getting Started(base URL 说明) | https://openapi.felo.ai/docs/getting-started |
兼容接口省掉了改代码的工作,但模型名和错误格式还是要按对方的实际情况来处理。