本页说明 SimpleLLMFunc 的 LLM 接口层设计,包括统一接口抽象、OpenAICompatible / OpenAIResponsesCompatible 两类适配器、密钥池和流量控制。
你会用到什么
LLM_Interface 统一定义 chat() 和 chat_stream() 的抽象基类。
OpenAICompatible 对接 OpenAI 兼容接口的默认实现,适合作为大多数项目的入口。
OpenAIResponsesCompatible 对接 OpenAI Responses API,同时保持与装饰器层相同的使用方式。
APIKeyPool 负责多 API Key 的负载均衡和任务分配。
TokenBucket 负责请求速率控制,避免把后端打到限流。
如果你只是想先接入模型,优先使用 OpenAICompatible.load_from_json_file(...) 或 OpenAIResponsesCompatible.load_from_json_file(...)。只有在你需要程序化控制密钥池或限流参数时,再手动实例化接口对象。
选择规则很简单:普通 chat/completions 兼容端点使用 OpenAICompatible;OpenAI Responses API 端点使用 OpenAIResponsesCompatible。两者共用同一种 provider.json 结构。
快速开始
创建 provider.json
{
"openai" : [
{
"model_name" : "gpt-3.5-turbo" ,
"api_keys" : [ "sk-key1" , "sk-key2" ],
"base_url" : "https://api.openai.com/v1" ,
"max_retries" : 5 ,
"retry_delay" : 1.0 ,
"rate_limit_capacity" : 20 ,
"rate_limit_refill_rate" : 3.0
}
],
"deepseek" : [
{
"model_name" : "deepseek-chat" ,
"api_keys" : [ "your-deepseek-key" ],
"base_url" : "https://api.deepseek.com/v1"
}
]
}
从配置文件加载模型
from SimpleLLMFunc import OpenAICompatible, OpenAIResponsesCompatible
llm = OpenAICompatible.load_from_json_file( "provider.json" )[ "openai" ][ "gpt-3.5-turbo" ]
responses_llm = OpenAIResponsesCompatible.load_from_json_file( "provider.json" )[ "openrouter" ][ "gpt-5.4" ]
交给装饰器使用
from SimpleLLMFunc import llm_function
@llm_function ( llm_interface = llm)
async def my_task ( text : str ) -> str :
"""处理文本任务"""
pass
组件说明
LLM_Interface 是所有 LLM 实现的抽象基类,定义统一的接口规范。它的目标是把调用方式和返回形式收敛到一致的接口上。OpenAICompatible 与 OpenAIResponsesCompatible 都继承自它。核心特点:
标准化接口:统一 chat() 和 chat_stream()
类型安全:配合 Python 类型注解使用
异步原生:适合高并发和事件流场景
可扩展:方便接入新的 OpenAI-compatible 服务
from abc import ABC , abstractmethod
from typing import Iterable, Dict, Optional, Literal, AsyncGenerator
from openai.types.chat.chat_completion import ChatCompletion
from openai.types.chat.chat_completion_chunk import ChatCompletionChunk
class LLM_Interface ( ABC ):
@abstractmethod
async def chat (
self ,
trace_id : str = get_current_trace_id(),
stream : Literal[ False ] = False ,
messages : Iterable[Dict[ str , str ]] = [{ "role" : "user" , "content" : "" }],
timeout : Optional[ int ] = None ,
* args ,
** kwargs ,
) -> ChatCompletion:
pass
@abstractmethod
async def chat_stream (
self ,
trace_id : str = get_current_trace_id(),
stream : Literal[ True ] = True ,
messages : Iterable[Dict[ str , str ]] = [{ "role" : "user" , "content" : "" }],
timeout : Optional[ int ] = None ,
* args ,
** kwargs ,
) -> AsyncGenerator[ChatCompletionChunk, None ]:
if False :
yield ChatCompletionChunk( id = "" , created = 0 , model = "" , object = "" , choices = [])
OpenAICompatible 是 LLM_Interface 的默认实现,支持任何兼容 OpenAI API 的服务,包括:
OpenAI
Deepseek
Anthropic Claude 兼容入口
火山引擎 Ark
百度千帆
Ollama、vLLM 等本地模型服务
其他 OpenAI-compatible 提供商
额外能力:
自动重试
Token 统计
限流控制
多 Key 轮换
OpenAIResponsesCompatible 适配器
OpenAIResponsesCompatible 用于对接 OpenAI Responses API,同时保持 @llm_function / @llm_chat 的装饰器使用方式不变。关键点:
与 OpenAICompatible 共用同一种 provider.json 结构
构造函数同样使用 APIKeyPool、model_name、base_url
装饰器层仍然先构造正常的 system/user messages,再由 adapter 把 system prompt 映射为 Responses API 的 instructions
reasoning={...} 等 Responses 能力由 adapter 透传,不需要把原生 Responses request schema 暴露给上层业务代码
APIKeyPool 使用小根堆维护各个密钥当前负载,优先分配最空闲的 key。你会得到:
自动负载均衡
并发状态跟踪
锁保护下的线程安全
按 provider_id 共享状态
堆结构:[(任务数, API密钥), ...]
堆顶永远是任务数最少的密钥
TokenBucket 使用经典令牌桶算法控制请求速率。算法要点:
以固定速率补充令牌
每次请求消耗令牌
桶容量有限,超出部分丢弃
桶中有足够令牌时允许突发请求
接口如何创建
from SimpleLLMFunc import OpenAICompatible
all_models = OpenAICompatible.load_from_json_file( "provider.json" )
gpt35 = all_models[ "openai" ][ "gpt-3.5-turbo" ]
gpt4 = all_models[ "openai" ][ "gpt-4" ]
deepseek = all_models[ "deepseek" ][ "deepseek-chat" ]
from SimpleLLMFunc import OpenAICompatible, APIKeyPool
key_pool = APIKeyPool(
api_keys = [ "sk-key1" , "sk-key2" , "sk-key3" ],
provider_id = "openai-gpt35" ,
)
llm = OpenAICompatible(
api_key_pool = key_pool,
model_name = "gpt-3.5-turbo" ,
base_url = "https://api.openai.com/v1" ,
max_retries = 5 ,
retry_delay = 1.0 ,
rate_limit_capacity = 20 ,
rate_limit_refill_rate = 3.0 ,
)
from SimpleLLMFunc import OpenAIResponsesCompatible
all_models = OpenAIResponsesCompatible.load_from_json_file( "provider.json" )
responses_llm = all_models[ "openrouter" ][ "gpt-5.4" ]
from SimpleLLMFunc import APIKeyPool, OpenAIResponsesCompatible
key_pool = APIKeyPool(
api_keys = [ "sk-key1" , "sk-key2" ],
provider_id = "openrouter-gpt-5.4-responses" ,
)
responses_llm = OpenAIResponsesCompatible(
api_key_pool = key_pool,
model_name = "gpt-5.4" ,
base_url = "https://openrouter.ai/api/v1" ,
max_retries = 5 ,
retry_delay = 1.0 ,
rate_limit_capacity = 20 ,
rate_limit_refill_rate = 3.0 ,
)
APIKeyPool 使用示例
from SimpleLLMFunc.interface import APIKeyPool
key_pool = APIKeyPool(
api_keys = [ "sk-key1" , "sk-key2" , "sk-key3" ],
provider_id = "my-provider" ,
)
key = key_pool.get_least_loaded_key()
key_pool.increment_task_count(key)
key_pool.decrement_task_count(key)
TokenBucket 参数建议
参数 类型 说明 推荐范围 capacityint 令牌桶容量 10-50 refill_ratefloat 每秒补充令牌数 0.5-5.0
常见场景:
# 高频 API(如 OpenAI)
capacity = 20
refill_rate = 3.0
# 标准 API
capacity = 10
refill_rate = 1.0
# 受限 API
capacity = 5
refill_rate = 0.5
生产环境模式
from SimpleLLMFunc import OpenAICompatible, llm_function
models = OpenAICompatible.load_from_json_file( "provider.json" )
fast_llm = models[ "openai" ][ "gpt-3.5-turbo" ]
powerful_llm = models[ "openai" ][ "gpt-4" ]
deepseek_llm = models[ "deepseek" ][ "deepseek-chat" ]
@llm_function ( llm_interface = fast_llm)
async def simple_task ( text : str ) -> str :
"""简单任务使用快速模型"""
pass
@llm_function ( llm_interface = powerful_llm)
async def complex_task ( text : str ) -> str :
"""复杂任务使用强大模型"""
pass
@llm_function ( llm_interface = llm)
async def robust_call ( text : str ) -> str :
"""可靠的 LLM 调用"""
pass
async def call_with_fallback ():
try :
return await robust_call( "test" )
except Exception as e:
print ( f "主模型失败: { e } " )
return await backup_call( "test" )
from SimpleLLMFunc.hooks.events import LLMCallEndEvent
from SimpleLLMFunc.hooks.stream import is_event_yield
async for output in summarize_text( "..." ):
if is_event_yield(output) and isinstance (output.event, LLMCallEndEvent):
print (output.event.usage)
least_loaded = llm.key_pool.get_least_loaded_key()
print ( f "最低负载密钥: { least_loaded } " )
print (llm.get_rate_limit_status())
最佳实践
为不同环境使用不同密钥集合
为高成本模型单独设置更保守的重试和限流参数
不要让多个环境共享同一个高频生产 key
依据供应商速率限制设置 capacity 和 refill_rate
对本地模型可适当设置更高值
发生限流时,优先先调参数,再考虑增加 key 数量
import asyncio
from typing import Optional
async def call_with_exponential_backoff (
llm_call ,
max_retries : int = 3 ,
base_delay : float = 1.0 ,
) -> Optional[ str ]:
for attempt in range (max_retries):
try :
return await llm_call()
except Exception :
if attempt == max_retries - 1 :
raise
await asyncio.sleep(base_delay * ( 2 ** attempt))
故障排除
增加 rate_limit_capacity 或 rate_limit_refill_rate
检查配置是否与供应商限制匹配
检查 API Key 是否有效且仍有配额
检查 base_url 是否正确
某些供应商不会返回完整 token 统计
框架会尽量估算,但并非总能做到完全准确
import logging
logging.basicConfig( level = logging. DEBUG )
logger = logging.getLogger( "SimpleLLMFunc" )
logger.setLevel(logging. DEBUG )
SimpleLLMFunc 的接口层把模型接入、限流和密钥管理集中到统一抽象里:
LLM_Interface 统一接口
OpenAICompatible 提供默认实现
APIKeyPool 处理多 key 负载均衡
TokenBucket 处理速率控制
这套设计既适合快速接入,也适合逐步扩展到生产环境。