本地大模型编程实战(38)实现一个通用的大模型客户端

由于大部分AI平台提供的API/接口都兼容 OpenAI API ,所以我们可以使用 OpenAI SDK 实现通用的 LLM(大语言模型) 客户端。

关于 OpenAI API 更多内容,可参考 程序员应该熟悉的概念(2)OpenAI API

本文讲述了如何实现一个简单的大模型客户端

兼容 OpenAI API 的平台

平台名称 base_url
openai api.openai.com/v1
anthropic api.anthropic.com/v1
mistral api.mistral.ai/v1
gemini generativelanguage.googleapis.com/v1beta/open...
cohere api.cohere.com/v1
xai api.x.ai/v1
openrouter openrouter.ai/api/v1
ollama http://localhost:11434/v1
bailian dashscope.aliyuncs.com/compatible-...
vllm http://localhost:8000/v1

本地部署的 Ollama 也兼容 OpenAI API,使用时无需 api-key 。合理的标准大大提高生产力!

定义变量

我们先定义一个变量,存储不同平台的 base_urlapi_key,这样在访问不同的平台时,使用该平台独有的配置信息即可。

python 复制代码
    PROVIDERS = {
        "openai": {
            "base_url": "https://api.openai.com/v1",
            "api_key_env": "OPENAI_API_KEY"
        },
        "anthropic": {
            "base_url": "https://api.anthropic.com/v1",
            "api_key_env": "ANTHROPIC_API_KEY"
        },
        "mistral": {
            "base_url": "https://api.mistral.ai/v1",
            "api_key_env": "MISTRAL_API_KEY"
        },
        "gemini": {
            "base_url": "https://generativelanguage.googleapis.com/v1beta/openai",
            "api_key_env": "GEMINI_API_KEY"
        },
        "cohere": {
            "base_url": "https://api.cohere.com/v1",
            "api_key_env": "COHERE_API_KEY"
        },
        "xai": {
            "base_url": "https://api.x.ai/v1",
            "api_key_env": "XAI_API_KEY"
        },
        "openrouter": {
            "base_url": "https://openrouter.ai/api/v1",
            "api_key_env": "OPENROUTER_API_KEY"
        },
        "ollama": {
            "base_url": "http://localhost:11434/v1",
            "api_key_env": None     # 使用任何字符串都可以
        },
        "bailian":{
            "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
            "api_key_env": "DASHSCOPE_API_KEY"
        },
        "vllm": {
            "base_url": "http://localhost:8000/v1",
            "api_key_env": None
        }
    }

本地部署的 ollamavllm 不需要 api_key。

这里将api-key存储在环境变量中,当然也可改造让它存储在配置文件甚至数据库中。

实现通用客户端类:LLMClient

在使用 LLM(大语言模型) 时,temperature 是很常用的参数: 它的数值在 0-1 之间,数值越小,确定性越强,数值越大,随机性越强。如果我们需要更加稳定准确的答案,那么这个数值应该小一点,如果想模拟李白写诗,这个数值应该大一点。

python 复制代码
class LLMClient:
    
    def __init__(self, provider="openai", api_key=None, temperature: float = 0.7):
        """
        初始化 LLM 客户端
        :param base_url: API 地址,例如 "http://localhost:8000/v1"
        :param api_key: API key(Ollama 等兼容实现可用任意字符串)
        :param model: 模型名称,例如 "qwen3" 或 "gpt-4o-mini"
        :param temperature: 采样温度([0-1],数值越大随机性越高)
        """
        if provider not in self.PROVIDERS:
            raise ValueError(f"Unsupported provider: {provider}")

        self.provider = provider
        self.temperature = temperature  # 保存默认 temperature
        config = self.PROVIDERS[provider]

        if not api_key and config["api_key_env"]:
            import os
            api_key = os.getenv(config["api_key_env"])
            if not api_key:
                raise ValueError(f"Missing API key, please set {config['api_key_env']}")

        if not api_key:
            api_key = "none"

        self.client = OpenAI(api_key=api_key, base_url=config["base_url"]) def chat(self, model, messages, stream=False, **kwargs): """ 普通调用: 返回字符串 流式调用: 返回生成器,每次 yield 新的 token """ # 如果用户没有传 temperature,则用默认的 # top_p、max_tokens 这些常用参数也可以通过kwargs设置 if "temperature" not in kwargs: kwargs["temperature"] = self.temperature if stream: response = self.client.chat.completions.create( model=model, messages=messages, stream=True, **kwargs ) def generator(): for chunk in response: delta = chunk.choices[0].delta.content if delta: yield delta return generator() else: resp = self.client.chat.completions.create( model=model, messages=messages, **kwargs ) return resp.choices[0].message.content 

kwargs 看起来怪怪的,但是其能力却很强,它可以传递任意数量的关键字参数。这些关键字参数会以字典的形式存储在 kwargs 中。

我们在 init 中设置了 temperature 的默认值,但是可以在调用 chat 方法时,通过 kwargs 覆盖它。

上面的类支持普通的调用,也支持流模式。下面使用本地部署的 ollama 测试一下:

python 复制代码
if __name__ == '__main__':
    model_name = "qwen3"
    llm = LLMClient(provider="ollama")

    print("流式模式结果:", end="", flush=True)
    for token in llm.chat(
        model=model_name,
        messages=[{"role": "user", "content": "用少于1000个字总结《西游记》"}],
        stream=True
    ):
        print(token, end="", flush=True)

    print()  # 换行

    result = llm.chat(model_name, [{"role": "user", "content": "用李白的风格给我写一首描写饮酒的诗"}])
    print("普通模式结果:\n", result)

输出结果就不贴了,有兴趣可以在后面下载代码自己玩一下。

总结

从以上的代码实践可以看出,基于标准的魔力,实现一个通用的大模型客户端就变得比较简单了。


代码

本文涉及的所有代码以及相关资源都已经共享,参见:

为便于找到代码,程序文件名称最前面的编号与本系列文章的文档编号相同。

🪐感谢您观看,祝好运🪐

相关推荐
大鸡腿同学2 小时前
【成长类】《只有偏执狂才能生存》读书笔记:程序员的偏执型成长地图
后端
0xDevNull2 小时前
MySQL数据冷热分离详解
后端·mysql
AI袋鼠帝2 小时前
OpenClaw(龙虾)最强开源对手!Github 40K Star了,又一个爆火的Agent..
后端
新知图书3 小时前
搭建Spring Boot开发环境
java·spring boot·后端
宸津-代码粉碎机4 小时前
Spring Boot 4.0虚拟线程实战调优技巧,最大化发挥并发优势
java·人工智能·spring boot·后端·python
小码哥_常4 小时前
一个Starter搞定六种防护,Spring Boot API的超强护盾来了
后端
熊猫钓鱼>_>4 小时前
从“流程固化“到“意图驱动“:大模型调智能体调Skill架构深度解析
ai·架构·大模型·llm·agent·skill·openclaw
小村儿6 小时前
连载04-最重要的Skill---一起吃透 Claude Code,告别 AI coding 迷茫
前端·后端·ai编程
IT_陈寒7 小时前
Vite的alias配置把我整不会了,原来是这个坑
前端·人工智能·后端
gelald7 小时前
Spring Boot - 自动配置原理
java·spring boot·后端