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

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

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

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

文章目录


兼容 OpenAI API 的平台

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

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

定义变量

我们先定义一个变量,存储不同平台的 base_url 和 api_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
        }
    }

本地部署的 ollama 和 vllm 不需要 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)

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

总结

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


代码

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

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

🪐感谢您观看,祝好运🪐

相关推荐
脚本自动化开发7 小时前
柔光屏平板怎么选?华为 MatePad Air Z 柔光版学
后端
锋行天下7 小时前
langgraph 后端发自定义数据,前端接收方法概括
人工智能·python
程序猿DD8 小时前
OctaFuse 2.19.0:重做管理后台界面与交互,模型目录同步更新
后端
金銀銅鐵8 小时前
带您看懂字节码指令(一):一帧里有什么
java·后端·ai编程
泯泷9 小时前
单个 AI 再强,为什么也干不过一支 AI 团队?
人工智能·llm·agent
浪遏9 小时前
认识 wm:从多平台发布到可扩展 CLI 的架构设计
人工智能
深蓝AI9 小时前
英伟达换帅当天,我先跑了一遍 GPU 环境体检:版本矩阵比人事更值得盯
人工智能·gpu
码事漫谈10 小时前
Agent 测评是什么?大白话讲一讲
后端
皮皮林55110 小时前
在 IDEA 里斗个地主不过分吧!
后端
罗西的思考10 小时前
【轻量化复刻大模型 / KIMI K3】AttnRes 模块交互式演示
人工智能·算法·机器学习