使用 gone.WrapFunctionProvider 快速接入第三方服务(下)—— LLM接入支持 openAI 和 deepseek

gone项目地址:https://github.com/gone-io/gone
文字例子源代码:


本文将介绍如何使用 gone.WrapFunctionProvider 和配置注入来快速接入大型语言模型(LLM)服务,包括 OpenAI 和 Deepseek。我们将详细说明这种方式的实现原理和最佳实践。

1. gone.WrapFunctionProvider 简介

Gone 框架提供了 gone.WrapFunctionProvider 这个强大的工具函数,它可以将一个普通的函数包装成 Provider。这种方式特别适合于:

  • 需要注入配置的场景
  • 需要创建单例的场景
  • 需要延迟初始化的场景
  • 需要错误处理的场景

对于 LLM 服务集成,这些特性尤其重要,因为我们通常需要管理 API 密钥、自定义基础 URL、设置超时和代理等配置。

2. 配置注入实现

在 Gone 框架中,配置注入是通过结构体标签(struct tag)实现的。以 Deepseek 为例:

param struct {
    config deepseek.Config `gone:"config,deepseek"`
}

这里的 gone:"config,deepseek" 标签表示:

  • config 表示这是一个配置项
  • deepseek 是配置的命名空间

3. 实战示例:OpenAI 和 Deepseek 集成

3.1 Deepseek 集成

让我们看一个完整的示例,展示如何使用 gone.WrapFunctionProvider 来集成 Deepseek:

func Load(loader gone.Loader) error {
    var load = gone.OnceLoad(func(loader gone.Loader) error {
        var single *deepseek.Client

        getSingleDeepseek := func(
            tagConf string,
            param struct {
                config Config `gone:"config,deepseek"`
                doer   g.HTTPDoer `gone:"*,optional"`
            },
        ) (*deepseek.Client, error) {
            var err error
            if single == nil {
                options := param.config.ToDeepseekOptions(param.doer)
                single, err = deepseek.NewClientWithOptions(param.config.AuthToken, options...)
                if err != nil {
                    return nil, gone.ToError(err)
                }
            }
            return single, nil
        }
        provider := gone.WrapFunctionProvider(getSingleDeepseek)
        return loader.Load(provider)
    })
    return load(loader)
}

3.2 OpenAI 集成

类似地,OpenAI 的集成也可以使用相同的模式:

func Load(loader gone.Loader) error {
    var load = gone.OnceLoad(func(loader gone.Loader) error {
        var single *openai.Client

        getSingleOpenAI := func(
            tagConf string,
            param struct {
                config Config `gone:"config,openai"`
                doer   g.HTTPDoer `gone:"*,optional"`
            },
        ) (*openai.Client, error) {
            var err error
            if single == nil {
                options := param.config.ToOpenAIOptions(param.doer)
                single, err = openai.NewClientWithOptions(param.config.AuthToken, options...)
                if err != nil {
                    return nil, gone.ToError(err)
                }
            }
            return single, nil
        }
        provider := gone.WrapFunctionProvider(getSingleOpenAI)
        return loader.Load(provider)
    })
    return load(loader)
}

这些代码实现了以下功能:

  1. 单例模式:通过闭包变量 single 确保只创建一个客户端实例
  2. 配置注入:通过结构体标签自动注入 LLM 服务配置
  3. 错误处理:使用 gone.ToError 统一错误处理
  4. HTTP 客户端注入:支持可选的 HTTP 客户端注入,便于自定义网络行为

4. 配置示例

4.1 Deepseek 配置

在项目的配置目录中创建 default.yaml 文件,添加以下 Deepseek 配置:

deepseek:
  authToken: "your-api-key"      # 你的 Deepseek API 密钥
  baseURL: ""                    # 可选:自定义 API 基础 URL
  timeout: 0                     # 可选:请求超时时间(秒)
  path: ""                       # 可选:API 路径(默认为 "chat/completions")
  proxyUrl: ""                   # 可选:HTTP 代理 URL

4.2 OpenAI 配置

类似地,OpenAI 的配置可以如下:

openai:
  authToken: "your-api-key"      # 你的 OpenAI API 密钥
  baseURL: ""                    # 可选:自定义 API 基础 URL
  timeout: 0                     # 可选:请求超时时间(秒)
  proxyUrl: ""                   # 可选:HTTP 代理 URL

4.3 多客户端配置

对于需要连接多个不同服务提供商的场景,可以使用不同的命名空间:

deepseek:
  authToken: "default-deepseek-key"

openai:
  authToken: "default-openai-key"

baidu:
  authToken: "baidu-api-key"
  baseURL: "https://custom.baidu.api.com"

aliyun:
  authToken: "aliyun-api-key"
  baseURL: "https://custom.aliyun.api.com"

5. 使用方式

5.1 基本使用

在应用中使用这些 Provider 非常简单:

type llmUser struct {
    gone.Flag
    deepseekClient *deepseek.Client `gone:"*"`
    openaiClient   *openai.Client   `gone:"*"`
}

func (s *llmUser) Use() {
    // 使用 Deepseek 客户端
    deepseekResp, err := s.deepseekClient.CreateChatCompletion(
        context.Background(),
        deepseek.ChatCompletionRequest{
            Model: "deepseek-chat",
            Messages: []deepseek.ChatCompletionMessage{
                {
                    Role:    "user",
                    Content: "你好!",
                },
            },
        },
    )
    
    // 使用 OpenAI 客户端
    openaiResp, err := s.openaiClient.CreateChatCompletion(
        context.Background(),
        openai.ChatCompletionRequest{
            Model: "gpt-3.5-turbo",
            Messages: []openai.ChatCompletionMessage{
                {
                    Role:    "user",
                    Content: "Hello!",
                },
            },
        },
    )
    // ...
}

5.2 多客户端使用

对于需要使用多个不同配置的客户端的场景:

type multiLLMUser struct {
    gone.Flag
    // Deepseek 客户端
    defaultDeepseek *deepseek.Client `gone:"*"`           
    baiduDeepseek   *deepseek.Client `gone:"*,baidu"`    
    
    // OpenAI 客户端
    defaultOpenAI   *openai.Client   `gone:"*"`           
    aliyunOpenAI    *openai.Client   `gone:"*,aliyun"`   
}

func main() {
    gone.NewApp(
        goneDeepseek.Load,
        goneOpenAi.Load,
    ).Run(func(u *multiLLMUser) {
        // 使用不同的客户端...
    })
}

6. 最佳实践

6.1 配置分离

  • 将配置放在独立的配置文件中
  • 使用命名空间避免配置冲突
  • 敏感信息如 API 密钥应通过环境变量注入

6.2 单例管理

  • 对于 LLM 客户端,始终使用单例模式以避免资源浪费
  • 使用 gone.OnceLoad 确保安全的单例初始化

6.3 错误处理

  • 使用 gone.ToError 包装错误
  • 在初始化时进行充分的错误检查
  • 对 API 调用进行适当的重试和超时处理

6.4 代理配置

对于网络受限环境,合理配置代理是必要的:

deepseek:
  authToken: "your-api-key"
  proxyUrl: "http://username:password@proxy.example.com:8080"

7. 总结

使用 gone.WrapFunctionProvider 和配置注入是一种优雅且高效的 LLM 服务接入方式。它具有以下优势:

  • 代码简洁,易于维护
  • 配置灵活,支持动态注入
  • 资源管理合理,支持单例模式
  • 错误处理统一,便于排查问题
  • 支持多种 LLM 服务提供商

通过这种方式,我们可以快速且规范地集成 OpenAI、Deepseek 等各种 LLM 服务,提高开发效率,同时保持代码的可维护性和可扩展性。无论是构建聊天机器人、内容生成工具还是其他 AI 驱动的应用,这种集成方式都能提供稳定可靠的基础设施支持。

相关内容

<think> 我们正在处理一个关于在Linux系统下调用DeepSeek API接入AI2Thor环境以实现LLM智能控制agent的问题。 根据用户需求,我们需要提供实现方法。由于问题涉及到多个步骤,我们将分步说明。 步骤1:环境准备 - 确保Linux系统已安装Python(建议3.8及以上版本) - 安装必要的Python包:openai(用于调用DeepSeek API,因为DeepSeek API与OpenAI API兼容),ai2thor(用于构建环境) 步骤2:获取DeepSeek API密钥 - 访问DeepSeek官网(https://platform.deepseek.com/)注册账号并获取API密钥。 步骤3:设置环境变量 - 将DeepSeek API密钥设置为环境变量,以便在代码中使用。根据用户使用的shell类型,执行以下命令之一: - 对于Bash:`echo "export DEEPSEEK_API_KEY='your_api_key_here'" >> ~/.bashrc && source ~/.bashrc` - 对于Zsh:`echo "export DEEPSEEK_API_KEY='your_api_key_here'" >> ~/.zshrc && source ~/.zshrc` - 注意:这里我们使用环境变量`DEEPSEEK_API_KEY`,因为DeepSeek的API密钥与OpenAI格式相似,但为了避免与OpenAI的变量混淆,我们单独命名。 步骤4:安装必要的Python包 - 打开终端,执行以下命令: ```bash pip install openai ai2thor ``` 步骤5:编写Python代码 - 创建一个Python文件(如`deepseek_ai2thor_agent.py`),并编写以下代码: ```python import os import openai from ai2thor.controller import Controller # 设置DeepSeek API密钥(DeepSeek API兼容OpenAI API,因此可以直接使用openai库) # 注意:DeepSeek的API基础URL需要设置为他们自己的 openai.api_key = os.getenv("DEEPSEEK_API_KEY") openai.api_base = "https://api.deepseek.com/v1" # DeepSeek的API地址 # 初始化AI2Thor控制器 controller = Controller(scene="FloorPlan1") # 选择场景 # 定义函数:使用DeepSeek模型生成控制指令 def get_agent_action(prompt): response = openai.ChatCompletion.create( model="deepseek-chat", # 使用DeepSeek模型 messages=[ {"role": "system", "content": "你是一个在AI2Thor环境中控制智能体的助手。请根据当前环境状态给出下一步动作。"}, {"role": "user", "content": prompt} ] ) return response.choices[0].message.content.strip() # 主循环:与环境交互 try: while True: # 获取当前环境状态(这里简化,实际中需要将环境状态转化为文本描述) # 例如:获取当前场景的图像或物体列表,然后转化为文本描述 current_state = "你当前在客厅,面前有一个沙发一个电视。" user_input = input("请输入你的指令(或输入'exit'退出): ") if user_input.lower() == 'exit': break # 构建提示词,包括当前状态用户指令 prompt = f"当前状态:{current_state}\n用户指令:{user_input}\n请给出智能体的动作(如:向前移动,左转,抓取电视等):" action = get_agent_action(prompt) print(f"智能体执行动作: {action}") # 根据生成的action执行AI2Thor中的动作(这里需要将自然语言动作映射到AI2Thor的API) # 例如:如果action是“向前移动”,则调用controller.step("MoveAhead") # 注意:这里需要一个从自然语言到AI2Thor动作的映射函数,由于时间关系,我们仅作示例 if "向前" in action: controller.step("MoveAhead") elif "后退" in action: controller.step("MoveBack") elif "左转" in action: controller.step("RotateLeft") elif "右转" in action: controller.step("RotateRight") # 其他动作映射... else: print(f"无法识别的动作: {action}") finally: controller.stop() ``` 步骤6:运行代码 - 在终端运行:`python deepseek_ai2thor_agent.py` 注意:上述代码是一个简化的示例,实际应用中需要: 1. 将AI2Thor的环境状态(如物体列表、位置等)转化为文本描述,以便输入给大模型。 2. 完善自然语言动作到AI2Thor动作的映射,可能需要设计更复杂的解析逻辑。 引用说明: - 关于DeepSeek API的使用,参考了其官方文档(由于没有具体引用,这里不标注,但实际开发中应参考官方文档)[^1]。 - AI2Thor的控制方法参考了其GitHub仓库的示例[^2]。 以上就是在Linux系统下调用DeepSeek API接入AI2Thor环境实现LLM智能控制agent的基本方法。 §§相关问题§§ 1. 如何将AI2Thor环境状态转化为适合大语言模型输入的文本描述? 2. DeepSeek API调用有哪些参数可以调整以提高响应质量? 3. 如何优化自然语言动作到AI2Thor动作的映射? </think> 以下是在Linux系统下调用DeepSeek API接入AI2Thor环境实现LLM智能控制agent的完整方法: ### 1. 环境配置准备 ```bash # 创建虚拟环境 python -m venv ai2thor_agent source ai2thor_agent/bin/activate # 安装核心依赖 pip install openai ai2thor numpy pillow ``` ### 2. 获取API凭证 1. 访问[DeepSeek平台](https://platform.deepseek.com/)获取API密钥 2. 设置环境变量: ```bash # 添加到 ~/.bashrc 或 ~/.zshrc echo 'export DEEPSEEK_API_KEY="sk-xxxxxxxx"' >> ~/.bashrc source ~/.bashrc ``` ### 3. 基础控制框架代码 ```python import os import openai from ai2thor.controller import Controller # 配置DeepSeek API openai.api_key = os.getenv("DEEPSEEK_API_KEY") openai.api_base = "https://api.deepseek.com/v1" # DeepSeek专用端点 class AI2ThorAgent: def __init__(self): self.controller = Controller( scene="FloorPlan28", # AI2Thor场景 gridSize=0.25, renderDepthImage=True, renderInstanceSegmentation=True ) def get_environment_state(self): """获取当前环境状态描述""" event = self.controller.last_event return f""" 当前位置: {event.metadata['agent']['position']} 可交互对象: {[obj['name'] for obj in event.metadata['objects'] if obj['visible']]} 当前任务: 寻找厨房中的咖啡杯 """ def get_llm_response(self, prompt): """调用DeepSeek API获取决策""" response = openai.ChatCompletion.create( model="deepseek-chat", messages=[ {"role": "system", "content": "你是一个在3D环境中导航的AI助手,请给出具体的动作指令"}, {"role": "user", "content": prompt} ] ) return response.choices[0].message.content def execute_action(self, action): """执行AI生成的指令""" action_map = { "前进": "MoveAhead", "后退": "MoveBack", "左转": "RotateLeft", "右转": "RotateRight", "拾取": "PickupObject", # 可扩展更多动作 } if action in action_map: self.controller.step(action_map[action]) def run(self, max_steps=20): """主控制循环""" for step in range(max_steps): state = self.get_environment_state() prompt = f"{state}\n请给出下一步动作指令:" action = self.get_llm_response(prompt) print(f"Step {step}: {action}") self.execute_action(action) if __name__ == "__main__": agent = AI2thorAgent() agent.run() ``` ### 4. 关键集成技术说明 1. **状态表示转换**:将AI2Thor的3D环境状态转换为LLM可理解的文本描述 2. **动作映射**:建立自然语言指令到AI2Thor动作的映射关系 3. **提示工程优化**:使用结构化提示模板提升决策准确性 ```python PROMPT_TEMPLATE = ''' 环境状态: {state_description} 可执行动作: [前进,后退,左转90度,右转90度,拾取<对象>,打开<对象>] 任务目标: {current_goal} 请用单个动作指令响应,不要解释 ''' ``` ### 5. 高级优化技巧 1. **视觉信息整合**:添加视觉基础模型处理图像输入 ```python from PIL import Image def get_visual_description(event): img = Image.fromarray(event.frame) # 使用CLIP等模型生成图像描述 return "画面显示一个现代厨房,中央有岛台" ``` 2. **记忆增强**:添加对话历史保持上下文连贯 ```python self.memory = [{"role": "system", "content": "你是家居助手..."}] def update_memory(self, content, role="assistant"): self.memory.append({"role": role, "content": content}) ``` 3. **安全机制**:添加动作验证层防止非法操作 ```python def validate_action(self, action): valid_actions = ["MoveAhead", "MoveBack", ...] return action in valid_actions ``` ### 6. 部署与执行 ```bash # 启动智能体 (需X11转发或虚拟帧缓冲) xvfb-run -s "-screen 0 1024x768x24" python deepseek_ai2thor_agent.py # 无头模式渲染设置 export DISPLAY=:99 ``` [^1]: DeepSeek API调用参考其官方RESTful接口规范 [^2]: AI2Thor环境配置需满足最小硬件要求
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dapeng-大鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值