返回文章列表

Open ai接口协议

28 min read
Open ai接口协议

https://mp.weixin.qq.com/s/smt8VjtHI53-MWGuijagwQ

虽然这个库的名字叫 openai,但在 AI Agent 开发圈子里,它更像是一个 “万能遥控器”。因为 DeepSeek、Moonshot(Kimi)、阿里通义千问等大多数模型厂商,都主动适配了这个库的格式。

核心概念:Client(客户端)

使用这个库的第一步,永远是实例化一个 Client。这就好比你拿起电话,准备拨号。

from openai import OpenAI

# 初始化客户端
client = OpenAI(
    # 1. api_key: 你的身份通行证
    api_key="sk-...", 
    
    # 2. base_url: AI LLM服务器地址
    # 如果不填,默认发送给 OpenAI 美国官网
    # 如果填了 DeepSeek 的地址,就发送给 DeepSeek
    base_url="https://api.deepseek.com" 
)

核心方法:chat.completions.create

这是 Agent 开发中最常用的方法。它的字面意思是:“基于对话历史,创建一个补全(回复)”。

  1. 基础代码结构:
response = client.chat.completions.create(
    model="deepseek-chat",           # 用哪颗大脑
    messages=[...],                  # 对话上下文
    temperature=0.7,                 # 创造力调节
    max_tokens=1000,                 # 字数限制
    response_format={"type": "text"} # 输出格式;也可以是 "json_object"
)
print(response.choices[0].message.content)
  1. 参数解析 (Parameters)

System prompt和user prompt

理解 System Prompt(系统提示词)和 User Prompt(用户提示词)的区别,就像理解 “人设”和“台词” 的区别一样重要。

在 OpenAI/DeepSeek 的 API 调用中,它们是 messages 列表里两个不同的角色 (role)。

System Prompt (系统提示词):上帝视角/出厂设置。它定义了 AI “是谁”、“怎么说话”、“必须遵守什么规则”。它是静态的,通常由 开发者(你) 写死在代码里。

User Prompt (用户提示词):具体任务/外界输入。它告诉 AI “现在要做什么”。它是动态的,通常来自最终用户的输入。(变量)

核心对象:messages (对话列表)

这是大模型的“短期记忆”。你传给它什么,它就记得什么。

messages = [
    # 第一条通常是 System,定基调
    {"role": "system", "content": "你是一个严肃的数学老师。"},
    
    # 历史对话(可选):如果你想让它记得刚才说过的话,要把历史记录手动塞进来
    {"role": "user", "content": "1+1等于几?"},
    {"role": "assistant", "content": "等于2。"},
    
    # 当前问题
    {"role": "user", "content": "那2+2呢?"}
]

这里不展开,后面的章节会详细讲述这个字段,它太核心了。

tools调用

tool定义

# 定义一个简单的“查天气”工具描述
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_current_weather",
            "description": "获取指定城市的当前天气情况",
            "parameters": {
                "type": "object",
                "properties": {
                    "location": {
                        "type": "string",
                        "description": "城市名,例如:北京, 上海",
                    },
                    "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]},
                },
                "required": ["location"],
            },
        },
    }
]

询问大模型

第一次调用:提供tools并获取tools调用决定

from openai import OpenAI
import json

client = OpenAI(api_key="your-api-key")

messages = [{"role": "user", "content": "帮我看看上海现在的天气怎么样?"}]

# 第一次请求
response = client.chat.completions.create(
    model="gpt-4o",
    messages=messages,
    tools=tools,
    tool_choice="auto" # 自动决定是否使用工具
)

response_message = response.choices[0].message
tool_calls = response_message.tool_calls

# 检查模型是否想调用工具
if tool_calls:
    print(f"模型想要调用工具: {tool_calls[0].function.name}")

第二次调用:回传执行结果

这是 Agent 逻辑中最容易出错的地方:你必须把模型返回的 response_message 原样放回上下文,再追加一条 role: tool 的消息。

if tool_calls:
    # 1. 把模型刚才生成的那个包含 tool_calls 的消息加入历史(非常重要!)
    messages.append(response_message)

    # 2. 模拟本地执行函数(在 Java 中可能是调一个 Service 或 DAO)
    for tool_call in tool_calls:
        function_args = json.loads(tool_call.function.arguments)
        # 假设我们执行了本地逻辑
        observation = {"location": "上海", "temperature": "22", "unit": "celsius", "description": "多云"}
        
        # 3. 把执行结果放入消息列表
        messages.append({
            "tool_call_id": tool_call.id, # 必须对应上面的 ID
            "role": "tool",
            "name": "get_current_weather",
            "content": json.dumps(observation),
        })

    # 4. 发起第二次请求,让模型总结结果
    second_response = client.chat.completions.create(
        model="gpt-4o",
        messages=messages,
    )
    print(second_response.choices[0].message.content)

格式化输出

底层约束 (response_format)

这一层能保证是 JSON,但不保证字段。

这是 API 服务端的一个**“强力开关”**。

deepseek 为例,你可以查看文档:https://api-docs.deepseek.com/zh-cn/guides/json_mode。

image

只要在请求API服务时给出限制参数:

response_format={"type": "json_object"}
  • • 它的作用:它在模型生成的底层(概率分布层面)强行干预。它像一个严苛的**“语法警察”**,按住了 AI 的手。

  • • 效果:开启后,模型吐出的第一个字符必须是 {,最后一个字符必须是 }。它物理上杜绝了 AI 说“好的,结果如下...”这类废话的可能性。

  • • 局限性:它只保证输出的是合法的 JSON 语法(括号配对、逗号正确),但不保证里面的字段是你想要的。它可能输出 {"hello": "world"},而你想要的是 {"price": 10}

json schema(字段、类型定义)--pydantic

核心返回值:Response Object

{
  "id": "chatcmpl-123",               // 此次请求的唯一标识符
  "object": "chat.completion",        // 对象类型,始终为 chat.completion
  "created": 1677652288,              // Unix 时间戳(秒)
  "model": "gpt-4o-2024-05-13",       // 实际使用的模型版本
  "system_fingerprint": "fp_44706d4fc2", // 模型运行的后端配置指纹(用于排查复现问题)
  "choices": [                        // 核心内容数组(通常只有一个元素)
    {
      "index": 0,
      "message": {                    // 模型生成的对话消息
        "role": "assistant",
        "content": "你好!有什么我可以帮你的?",
        "tool_calls": null            // 如果触发了函数调用,这里会有具体参数
      },
      "logprobs": null,               // 词元生成的对数概率(需在请求中开启)
      "finish_reason": "stop"         // 中止原因:stop(自然结束), length(达到最大token), tool_calls(触发工具)
    }
  ],
  "usage": {                          // Token 消耗统计
    "prompt_tokens": 9,               // 输入提示词占用的 token
    "completion_tokens": 12,          // 模型生成的 token
    "total_tokens": 21,               // 总计(计费依据)
    "completion_tokens_details": {    // 详细消耗(如推理模型会有 reasoning_tokens)
      "reasoning_tokens": 0
    }
  }
}