跳转到主要内容
本页说明 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 结构。

快速开始

1

创建 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"
    }
  ]
}
2

从配置文件加载模型

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"]
3

交给装饰器使用

from SimpleLLMFunc import llm_function

@llm_function(llm_interface=llm)
async def my_task(text: str) -> str:
    """处理文本任务"""
    pass

组件说明

LLM_Interface 是所有 LLM 实现的抽象基类,定义统一的接口规范。它的目标是把调用方式和返回形式收敛到一致的接口上。OpenAICompatibleOpenAIResponsesCompatible 都继承自它。核心特点:
  • 标准化接口:统一 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=[])
OpenAICompatibleLLM_Interface 的默认实现,支持任何兼容 OpenAI API 的服务,包括:
  • OpenAI
  • Deepseek
  • Anthropic Claude 兼容入口
  • 火山引擎 Ark
  • 百度千帆
  • Ollama、vLLM 等本地模型服务
  • 其他 OpenAI-compatible 提供商
额外能力:
  • 自动重试
  • Token 统计
  • 限流控制
  • 多 Key 轮换
OpenAIResponsesCompatible 用于对接 OpenAI Responses API,同时保持 @llm_function / @llm_chat 的装饰器使用方式不变。关键点:
  • OpenAICompatible 共用同一种 provider.json 结构
  • 构造函数同样使用 APIKeyPoolmodel_namebase_url
  • 装饰器层仍然先构造正常的 system/user messages,再由 adapter 把 system prompt 映射为 Responses API 的 instructions
  • reasoning={...} 等 Responses 能力由 adapter 透传,不需要把原生 Responses request schema 暴露给上层业务代码
APIKeyPool 使用小根堆维护各个密钥当前负载,优先分配最空闲的 key。你会得到:
  • 自动负载均衡
  • 并发状态跟踪
  • 锁保护下的线程安全
  • provider_id 共享状态
堆结构:[(任务数, API密钥), ...]
堆顶永远是任务数最少的密钥
TokenBucket 使用经典令牌桶算法控制请求速率。算法要点:
  1. 以固定速率补充令牌
  2. 每次请求消耗令牌
  3. 桶容量有限,超出部分丢弃
  4. 桶中有足够令牌时允许突发请求

接口如何创建

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"]

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
  • 依据供应商速率限制设置 capacityrefill_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_capacityrate_limit_refill_rate
  • 检查配置是否与供应商限制匹配
  • 检查 API Key 是否有效且仍有配额
  • 检查 base_url 是否正确
  • 某些供应商不会返回完整 token 统计
  • 框架会尽量估算,但并非总能做到完全准确
import logging

logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger("SimpleLLMFunc")
logger.setLevel(logging.DEBUG)

总结

SimpleLLMFunc 的接口层把模型接入、限流和密钥管理集中到统一抽象里:
  1. LLM_Interface 统一接口
  2. OpenAICompatible 提供默认实现
  3. APIKeyPool 处理多 key 负载均衡
  4. TokenBucket 处理速率控制
这套设计既适合快速接入,也适合逐步扩展到生产环境。