Skip to content

LV010-AI的API调用

这一部分主要是 API 的调用、参数、对话与状态管理。

一、概述

AI 助手应该是什么样的?

(1)懂我们的意图

(2)深入聊天

(3)记得我们的喜好

这样的应用背后,我们需要解决三个核心问题:

  • 如何让它“听话”并且”说的好“?参数控制
  • 如何让“它不健忘”,能连贯的对话?对话管理
  • 如何让它“认识我们”,提供个性化服务?状态管理

二、起点:API 调用

1. 什么是 API 调用

API(Application Programming Interface,应用程序编程接口),它属于一个中间人的角色。模型本身只是一个文件或程序,API 是一种让它能够被远程调用的 通信方式

下面是 ai 给我举得一个例子:

  • 你(你的应用程序):一位想去吃饭的顾客。你想吃一道复杂的菜,比如“佛跳墙”,但你不知道怎么做,也没有厨房和食材。
  • 大模型(比如 GPT-4、文心一言等):一个设备顶级、厨艺精湛的后厨。它拥有所有昂贵的厨具(成千上万的 GPU)、珍贵的食材(海量数据)和顶尖的厨师(复杂的算法)。但这个后厨不对外开放,你不能直接进去自己动手。
  • API 餐厅的服务员和菜单。

(1)菜单(API 文档):告诉你这家厨房能做什么菜(比如“文本总结”、“代码生成”、“翻译”、“问答”),以及你需要提供什么信息(比如你想总结的“原文是什么?”)。

(2)服务员(API 服务):你按照菜单点餐(通过代码发送一个请求),服务员会把你的订单准确无误地送到后厨。厨房做好菜后,服务员再把香喷喷的“佛跳墙”(模型的回答)端回给你。

所以,大模型的 API 就是一个标准化的“通信窗口”或“服务协议” 。我们的程序不需要知道大模型内部是如何工作的,只需要按照 API 文档规定的格式(比如发送一段 JSON 文本),向一个指定的网络地址(API 端点)发送请求,就能得到大模型返回的结果。

2. 什么时候需要 API?

那我们要是把大模型部署在本地,还需要这个 api 吗?什么时候才需要 api 呢?

本地部署的模型本身不需要依赖外部的 API,但为了让它能被方便地使用,我们通常会为它“创建”一个本地的 API 服务。我们可以用一个简单的比喻来理解:

  • 本地部署的模型:就像厨房里的 全套厨具和食材
  • 模型文件:就是菜谱。
  • 为模型创建本地 API:相当于在家里定了一个 点餐和上菜的规则

(1)不需要 api 的情况:直接调用(“自己下厨”)

这种方式下,我们和模型是“零距离”接触。比如我们现在写了一个 Python 脚本,用来处理本地文件。脚本直接加载模型,处理数据,然后输出结果。整个过程中,只有我们这个脚本在和模型互动。

优点简单、快速、延迟极低。因为没有网络通信的开销。

缺点不灵活。这个模型能力被“锁死”在这个脚本里了,其他程序或用户无法使用它。

(2)需要 API:服务化部署(“在家开家庭餐厅”)

这种方式下,我们为模型创建一个服务,让它能接受来自各方的请求。比如我们想开发一个带界面的 本地 Web 应用(一个桌面版的 AI 聊天助手?)。然后还想让公司内网的 其他同事或程序 也能使用我们服务器上的这个模型。

这个时候我们需要使用像 FastAPIFlask 这样的框架,写一个简单的程序。这个程序会加载模型,并监听一个网络端口(如 http://localhost:8000)。其他程序(如的网页前端、其他同事的脚本)就可以像访问网站一样,向这个地址发送请求来使用模型。

优点灵活、可共享、易于集成。模型变成了一个标准化的服务,可以被任何能发送网络请求的程序调用。

缺点:引入了微小的网络延迟,部署稍微复杂一点。

Tips:现在有很多工具可以帮我们一键把本地模型变成 API 服务,极大简化了过程:

  • Ollama:部署和运行开源模型的最流行工具,运行后自动提供一个本地 API。
  • LM Studio:图形化界面工具,同样在启动模型后提供本地 API 端点。
  • vLLM:一个高性能的推理引擎,专为生产环境设计,核心就是提供 API 服务。

使用这些工具,我们基本上只需要执行一条命令,它们就会在本地(如 http://localhost:11434)启动一个兼容 OpenAI API 格式的服务,让我们可以像调用 GPT-4 的 API 一样调用我们自己的本地模型。

3. API 调用的本质

API 调用并不是简单的“请求——响应”,而是一次“意图的编码和解码的过程”。

  • 编码意图:把人类语言和指令转换为结构化数据,例如,JSON 格式。
  • API 传输:通过标准协议传递编码后的意图。
  • 解码响应:将 AI 的输出换回可理解的形式。

4. 与 AI 对话的“信使”

完成 api 调用需要下面几个内容:

  • Endpoint(服务入口):API 的网络地址,指向一个特定的 ai 服务。相当于门牌号。
  • Headers(握手协议):身份验证与数据格式建立安全的通信通道。相当于身份证。
  • Payload(结构化信件):指令、参数和上下文,承载全部的“意图”。相当于包裹。

4.1 Endpoint(服务入口)

去哪里找 AI?上面已经介绍了 API 调用,那肯定是要找一个 API 的网络地址(URL),例如 Deepseek 官网中为我们提供的 base_url(可以去接口文档查):

markdown
https://api.deepseek.com/v1

Tips:

官网也会有调用的示例:

python
# Please install OpenAI SDK first: `pip3 install openai`
import os
from openai import OpenAI

client = OpenAI(
    api_key=os.environ.get('DEEPSEEK_API_KEY'),
    base_url="https://api.deepseek.com")

response = client.chat.completions.create(
    model="deepseek-chat",
    messages=[
        {"role": "system", "content": "You are a helpful assistant"},
        {"role": "user", "content": "Hello"},
    ],
    stream=False
)

print(response.choices[0].message.content)

申请好 Deepseek 的 API Key 后就可以使用上面的 Python 脚本访问 Deepseek API,上面的例子是非流式输出,可以吧 stream 设置为 true 来使用流式输出。

这个 API 的 作用:指向特定的 ai 服务(例如文本生成、图像理解等)。

4.2 Headers(握手协议)

这个 Headers 会包含 Authorization(认证)和 Content-Type(内容类型)。

  • Authorization 是用来证明“你是你”,也就是进行身份验证,它会携带 API key(一般是 Authorization: Bearer YOUR_API_KEY)。这个就是我们在对应的大模型服务提供商哪里申请的。但也不是所有的大模型服务都需要,一些在线的大模型,需要对外服务的大模型为了建立安全、规范的通信通道,一般都是需要身份验证,但是有一些本地的大模型服务,例如后面会使用的 Ollama 运行本地大模型的时候,就可以不用 API key。

  • Content-Type 内容类型,一般是 Content-Type: application/json,它用来声明数据格式,是我们和大模型沟通的语言规范,例如 JSON 格式。

4.3 Payload(结构化信件)

可以先来看一段 json 格式的 payload:

json
{
    "model": "deepseek-chat",
    "messages": {
        {"role": "user", "content": "Hello"},
    },
    "temperature": 0.7
}

payload 就是把指令、参数、上下文打包成大模型可读的格式,一般是 JSON。它的作用就是承载我们要传达的全部“意图”。

4.4 总结

说明:下面的总结由 AI 生成。

一次完整的 AI API 调用过程就像在高级餐厅点餐的完整体验,让我们用生动的餐厅比喻来详细说明:

阶段一:你的应用程序发出订单(构建请求)

你在应用里输入问题(比如:"写一首关于秋天的诗")并点击发送。

你的应用程序(服务员)立刻开始工作,它会根据预设的规则,将你的问题和其他参数打包成一个标准的 "订单"——也就是一个 HTTP 请求。

这个订单包含几个关键部分:

  • 餐厅地址:API 的端点
    • 使用 SDK 时:只需要设置 base_url 为 https://api.deepseek.com,SDK 会自动处理完整路径
    • 直接 HTTP 请求时:需要完整 URL,如 https://api.deepseek.com/v1/xxx
  • 会员卡:你的 API 密钥,放在请求头里,证明你是合法顾客
  • 菜单和口味要求:请求体,通常是 JSON 格式,包含:
    • model:你要哪位 "主厨" 来做(比如 deepseek-chat
    • messages:你的具体问题和对话历史
    • temperature:你希望主厨的创造力有多高(0 是严格按菜谱,1 是自由发挥)
    • max_tokens:这道菜最多上多少 "道"(控制回答长度)

技术实现示例:

python
import os
from openai import OpenAI

# 建立连接(找到餐厅)
client = OpenAI(
    api_key=os.environ.get('DEEPSEEK_API_KEY'),  # 你的会员卡
    base_url="https://api.deepseek.com"          # 餐厅地址
)

# 下订单
response = client.chat.completions.create(
    model="deepseek-chat",                       # 选择主厨
    messages=[                                   # 点单内容
        {"role": "system", "content": "你是一个专业的AI助手"},
        {"role": "user", "content": "请介绍一下AI API调用的基本流程"}
    ],
    temperature=0.7,                            # 口味要求
    max_tokens=1000,                            # 份量控制
    stream=False                                # 上菜方式
)

阶段二:订单穿越网络(网络传输)

这个 HTTP 请求通过互联网发送出去。它会经过你的路由器、运营商网络、各种骨干网路由器,最终抵达 AI 服务商的服务器。这个过程就像服务员把你的订单从餐桌送到厨房入口,中间可能要穿过餐厅的大堂。为了保证订单不被偷看或篡改,整个过程通常是加密的(HTTPS)。

阶段三:AI 服务商内部处理(餐厅后厨的复杂运作)

这是最核心、最复杂的部分。你的请求进入 AI 服务商的庞大系统后,会经历以下步骤:

(1)抵达大门:API 网关(前台兼保安)

  • 身份验证:检查你的 API 密钥是否有效、是否有余额
  • 速率限制:防止你点单太快把厨房搞乱(比如每分钟最多 60 次)
  • 请求校验:检查你的订单格式对不对(JSON 是否合法)

(2)进入等待区:任务队列(取餐号系统)

  • AI 推理非常消耗计算资源,如果所有订单都直接冲向主厨,系统会崩溃
  • 请求会被放入任务队列里排队,保证公平有序
  • 实现削峰填谷,即使瞬间来一万单,厨房也能按自己的节奏处理

(3)预处理:备菜

  • 内容审查:检查你的提问是否包含违规内容
  • 提示词优化:在你的要求上加点 "标准配方",引导主厨做出更符合预期的菜
  • 参数解析:提取 temperature、max_tokens 等参数,准备好交给主厨

(4)核心烹饪:模型推理(明星主厨上场)

  • 分词:主厨不认识汉字,只认识数字。他会先把你的问题切分成一个个最小的单元(Token),然后转换成数字 ID
  • 模型计算:这些数字 ID 被送入加载在 GPU 上的神经网络模型中,模型会一层一层地处理这些输入
  • 自回归生成:模型预测出第一个词,然后把这个词也作为输入,再去预测第二个词,如此循环直到生成完整回答

(5)出锅装盘:后处理与响应

  • 格式化:将结果打包成标准的 JSON 格式
  • 最终审查:再次快速检查生成的内容是否安全合规
  • 计费信息:记录这次请求消耗了多少 Token

阶段四:返回你的餐桌(响应返回)

封装好的 HTTP 响应原路返回,穿过 API 网关,经过互联网,最终回到你的应用程序。这里有一个关键点:流式传输 vs 非流式传输

  • 非流式:等主厨把整道菜都做完,一次性端上桌
  • 流式:主厨每炒好一小部分,服务员就立刻端给你(打字机效果)

应用呈现:

python
# 接收菜品并享用
if response.choices:
    ai_response = response.choices[0].message.content  # 提取主厨的杰作
    print(ai_response)
else:
    print("抱歉,今天主厨休息了")

响应数据结构:

json
{
    "id": "chatcmpl-123",
    "model": "deepseek-chat",
    "choices": [
        {
            "message": {
                "role": "assistant",
                "content": "AI API调用的基本流程包括..."
            }
        }
    ],
    "usage": {
        "prompt_tokens": 9,
        "completion_tokens": 12,
        "total_tokens": 21
    }
}

完整流程示意图:

markdown
[] <-> [你的App] <--(HTTP请求)--> [互联网] <--(HTTPS)--> [AI服务商]
                                                      |
                                                      V
                                                [API网关] (鉴权, 限流)
                                                      |
                                                      V
                                                [任务队列] (排队)
                                                      |
                                                      V
                                   [预处理服务] (审查, 解析参数)
                                                      |
                                                      V
                            [模型推理服务] (在GPU上进行分词、计算、生成)
                                                      |
                                                      V
                                   [后处理服务] (格式化JSON, 计费)
                                                      |
                                                      V
                                                [API网关]
                                                      |
                                                      V
                                                [互联网]
                                                      |
                                                      V
[] <--(显示结果)--> [你的App] <--(HTTP响应)--> [互联网] <--(HTTPS)--> [AI服务商]

三、前面的三个核心问题

1. 参数

1.1 简介

参数是控制 AI 行为的关键,通过参数的调整,我们可以精确控制 ai 的输出风格,创造力和内容长度等。参数的本质其实影响的是模型的“决策”。AI 生成文本的本质是预测下一个最可能的词,ai 本身是不理解这些词的含义的,而参数最终影响的就是”可能性“的计算方式。

  • Temperature:控制创造性和确定性的平衡。例如 Temperature 越低,倾向于选择最高概率的词,输出更加的稳定、严谨、也更加的可预测,适合事实性的会打、技术文档等。而 Temperature 越高,就会给低概率的词更多出现的机会,输出就更加的随机、多样、更加有“创意”,适合创意写作,头脑风暴(万一就组合出了一个创造性的东西呢?万一呢,是吧)。

  • Max Tokens:限制 AI 回复的最大长度。控制 API 调用成本,避免资源浪费。

  • Top P:控制词汇选择的多样性。

1.2 如何管理

如何优雅的管理参数?可以将参数配置分离出来, 使业务逻辑更加清晰和可维护,例如:

python
# 好的设计
PRESETS ={
    "creative writer": {
        "temperature": 0.9,
        "max tokens": 1000
    },
    "fact checker": {
        "temperature": 0.1,
        "max tokens": 500
    }
}
# 调用时
params =PRESETS ["creative_writer"]

# API 调用
response =openai.ChatCompletion.create (
    model = "gpt-3.5-turbo",
    messages = messages,
    **params
)

2. 对话

2.1 短期记忆?

AI模型本身是无状态的每次请求都是独立的。那么如何能让AI拥有短期的记忆?如何当AI记住我们是谁?怎么记住历史,实现跟我们的连贯对话?

解决方案就是欺骗AI,让它自己以为自己记得,核心思想就是:把历史对话(前面输入的内容,AI输出的内容等)作为新的请求的一部分,一起发送给AI。

2.2 对话格式示例

例如,我们可以设计一个对话记录的列表Messages,它可以包含“角色——内容”,里面的角色包括:

  • System:代表系统级别的指令,通常用来放置提示词,提示词可以进一步控制(或者说覆盖)大模型的行为,可以用于设定AI的全行为和背景,具有高优先级,但同时也存在不稳定的风险

  • User:用户发出的指令。

  • Assistant:LLM 给出的回复。

【例】

python
messages = [
    {
        "role": "system",
        "content":"你是一个有帮助的助手。"
    },
    {
        "role": "user",
        "content": "你好"
    },
    {
        "role": "assistant",
        "content":"你好!有什么可以帮你的吗?"
    },
    {
        "role": "user",
        "content": "我刚才想说什么? "
    }
]

大模型所谓的“记忆”对话,其实是依赖于这个列表来传递信息的。

2.3 对话管理

对话管理就是AI的短期记忆,通过上下文的注入,让AI能够记住对话历史实现连贯的多轮交流。本质上就是一个不断追加和更新历史列表的过程。

一个问题:随着上下文越来越多,我们发给ai的内容越来越多,AI处理的成本也越来越高,所以很多大模型都设置了上下文长度,例如64KB、128KB,千问可以达到256KB。

3. 状态

3.1 状态管理

前面提到如何让AI"认识我们",记住用户的姓名、偏好等个人信息,提供个性化服务?这就需要状态管理来实现。状态管理是AI的长期记忆系统,通过持久化的存储机制,让AI能够记住用户的信息、偏好和历史交互,从而实现真正的个性化体验。

状态管理可以将底层无状态的AI服务,包装成用户感知上有状态体验的关键技术。

状态管理的核心价值:

  • 个性化服务:记住用户偏好,提供定制化体验
  • 上下文感知:了解用户习惯和历史交互
  • 持续学习:基于历史数据优化服务质量
  • 用户体验:减少重复信息输入,提高交互效率

3.2 长期记忆和短期记忆的对比

特性上下文(短期记忆)状态(长期记忆)
生命周期会话级(临时)应用级(持久)
内容完整的对话历史关键信息片段(如用户名、偏好)
存储内存中的列表变量、文件、数据库、缓存
作用维持对话连贯性提供个性化体验
更新频率每次对话更新按需更新
数据量相对较大相对较小

实际应用示例:

  • 短期记忆:记住当前对话中提到的"我刚才说的那个项目"
  • 长期记忆:记住用户"喜欢喝咖啡"、"住在北京"等个人信息

3.3 状态存储的载体选择

状态存储的选择取决于应用的规模、性能和持久性需求:

1. 内存变量(临时存储)

python
# 简单但易失性存储
user_preferences = {
    "user_id": "12345",
    "preferred_language": "中文",
    "theme": "dark",
    "last_login": "2024-01-15"
}
  • 优点:访问速度快,实现简单
  • 缺点:程序重启后数据丢失
  • 适用场景:开发测试、临时会话

2. 文件存储(轻量级持久化)

python
# JSON文件存储示例
import json

# 保存状态
def save_user_state(user_id, state):
    with open(f'user_{user_id}.json', 'w', encoding='utf-8') as f:
        json.dump(state, f, ensure_ascii=False, indent=2)

# 读取状态
def load_user_state(user_id):
    try:
        with open(f'user_{user_id}.json', 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        return {}
  • 优点:实现简单,数据持久化
  • 缺点:并发访问可能有问题,性能有限
  • 适用场景:单用户应用、小型项目

3. 数据库存储(企业级方案)

  • SQLite:轻量级,适合桌面应用
  • Redis:高性能内存数据库,适合缓存
  • MySQL/PostgreSQL:关系型数据库,适合复杂查询
  • MongoDB:文档数据库,适合灵活的数据结构

3.4 状态信息的提取策略

从用户输入中提取关键信息是状态管理的核心环节:

(1)基于规则的方法:关键词匹配、正则表达式匹配

python
def extract_user_info(text):
    info = {}
    
    # 关键词匹配
    if "我叫" in text:
        # 提取姓名:"我叫张三" -> "张三"
        name = text.split("我叫")[1].split(" ")[0]
        info["name"] = name
    
    # 正则表达式匹配
    import re
    email_match = re.search(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', text)
    if email_match:
        info["email"] = email_match.group()
    
    return info

(2)基于AI的智能提取:例如自然语言处理(Natural Language Processing,简称 NLP)技术等。

参考资料:

(3 封私信) 2025 年 AI 大模型应用开发的全攻略。 - 知乎