基于 FastAPI 与大语言模型 API 的哈吉咪聊天机器人开发实践

基于 FastAPI 与大语言模型 API 的哈吉咪聊天机器人开发实践

一、项目背景

随着大语言模型技术的发展,调用 AI 接口开发个性化聊天机器人,已经成为 Python 初学者学习人工智能应用开发的一种实践方式。

本项目使用 Python 作为开发语言,借助 FastAPI 搭建 Web 服务,并通过 OpenAI 兼容接口调用大语言模型,实现一个具有简单上下文记忆能力的聊天机器人。

与普通的问答程序不同,本项目还为机器人设置了特定的人格提示词,让它以一只可爱的“哈吉咪”的身份与用户交流,并在每次回答结束时添加“喵”,使交互过程更具趣味性。

项目的主要功能包括:

  1. 使用 FastAPI 创建 Web 应用。
  2. 通过大模型 API 实现智能对话。
  3. 使用消息列表保存聊天上下文。
  4. 通过系统提示词设置机器人的角色与回复风格。
  5. 提供 HTTP 接口,方便通过浏览器或接口调试工具进行测试。

二、开发环境与技术选型

本项目主要涉及以下技术。

1. Python

Python 是项目的核心开发语言,负责组织消息数据、调用模型接口以及处理返回结果。

2. FastAPI

FastAPI 是一个用于构建 Web API 的 Python 框架。本项目通过装饰器定义聊天接口,使外部程序能够向服务器发送请求并获取 AI 的回答。

3. OpenAI Python SDK

通过 OpenAI Python SDK,可以调用支持 OpenAI 兼容协议的大模型服务。只需要根据服务提供商的要求设置 API 密钥、接口地址和模型名称,就可以发起对话请求。

需要注意,虽然 SDK 的调用形式相似,但不同平台的接口地址、模型名称和支持的参数可能不同,应以实际服务商的文档为准。

4. Uvicorn

Uvicorn 是 ASGI 服务器,负责运行 FastAPI 应用,使本地程序能够通过 HTTP 接收请求。

三、项目实现过程

3.1 创建 FastAPI 应用

首先,导入 FastAPI 并创建应用实例:

from fastapi import FastAPI  # 导入 FastAPI 框架,用于创建 Web API 应用

app = FastAPI()  # 创建应用实例,后续的接口都注册在这个实例上

app 可以理解为整个 Web 服务的入口。通过 @app.get() 等装饰器,可以为应用添加不同的接口。

例如,项目使用 /chat 作为聊天接口的访问路径。

3.2 配置大模型 API

项目通过 OpenAI Python SDK 连接支持兼容协议的大模型服务。

安装依赖:

pip install fastapi openai uvicorn  # 安装 Web 框架、模型调用 SDK 和服务器

配置客户端时,需要准备服务商提供的 API 密钥、兼容接口地址以及可用的模型名称。

为了避免将密钥直接写入代码,可以通过环境变量读取:

import os  # 导入系统模块,用于读取环境变量
from openai import OpenAI  # 导入 OpenAI 兼容客户端

client = OpenAI(  # 创建大模型客户端
    api_key=os.getenv("ARK_API_KEY"),  # 从环境变量中读取 API 密钥
    base_url="https://ark.cn-beijing.volces.com/api/v3"  # 设置火山方舟兼容接口地址
)

上述地址适用于相应的火山方舟兼容接口场景。如果使用其他平台,应替换为该平台实际提供的地址。

另外,模型名称也需要根据账号实际开通的模型或推理接入点进行设置,不能直接假定不同平台的模型名称通用。

3.3 使用消息列表保存聊天上下文

为了让机器人能够参考之前的对话,项目使用列表 msgs 保存消息记录。

msgs = [  # 创建消息列表,用于保存对话上下文
    {  # 添加系统提示词
        "role": "system",  # system 表示系统级指令
        "content": "你是一只可爱的哈吉咪,每次回答完问题后都要喵一下"  # 定义机器人的角色和回复风格
    }
]

在大模型对话接口中,role 用于区分消息来源,常见的角色包括:

  • system:设置模型的行为规则和角色。
  • user:表示用户发送的消息。
  • assistant:表示 AI 生成的回答。

当用户发送问题时,程序会将用户消息添加到列表中;模型生成回答后,再将回答保存到列表中。下一次请求时,程序就可以把之前的对话一起发送给模型。

需要注意的是,这种方式只是在当前 Python 进程运行期间保存上下文。如果服务重启,消息记录就会丢失。此外,多个用户共用一个全局消息列表时,会出现不同用户的聊天内容相互混杂的问题,因此这种实现更适合单人本地演示。正式项目应按用户或会话分别存储消息。

3.4 编写聊天接口

原始代码采用 GET 请求,并通过参数 data 接收用户输入。例如,访问 /chat?data=你好 即可触发聊天逻辑。

对于聊天场景,更推荐使用 POST 请求,通过 JSON 请求体提交内容。这样更便于后续扩展,也可以避免将聊天内容直接放在 URL 中。

以下为调整后的完整示例:

import os  # 导入系统模块,用于读取环境变量
import uvicorn  # 导入 Uvicorn,用于启动 Web 服务
from fastapi import FastAPI  # 导入 FastAPI,用于创建接口
from openai import OpenAI  # 导入 OpenAI 兼容客户端
from pydantic import BaseModel  # 导入 BaseModel,用于定义请求数据格式

app = FastAPI()  # 创建 FastAPI 应用实例

client = OpenAI(  # 创建大模型 API 客户端
    api_key=os.getenv("ARK_API_KEY"),  # 从环境变量读取 API 密钥
    base_url="https://ark.cn-beijing.volces.com/api/v3"  # 设置火山方舟兼容接口地址
)

msgs = [  # 创建用于保存聊天上下文的列表
    {  # 添加系统提示词
        "role": "system",  # 指定消息类型为系统指令
        "content": "你是一只可爱的哈吉咪,每次回答完问题后都要喵一下"  # 设置机器人角色
    }
]

class ChatRequest(BaseModel):  # 定义聊天请求的数据结构
    data: str  # 声明 data 字段,要求用户提交字符串类型的聊天内容

@app.post("/chat")  # 创建 POST 聊天接口,访问路径为 /chat
def chat(request: ChatRequest):  # 接收并处理用户的聊天请求
    user_message = {"role": "user", "content": request.data}  # 将用户输入整理成模型需要的消息格式
    msgs.append(user_message)  # 将用户消息保存到上下文列表

    completion = client.chat.completions.create(  # 调用大模型生成回答
        model=os.getenv("ARK_MODEL"),  # 读取已配置的模型名称或推理接入点 ID
        messages=msgs  # 将历史对话一并发送给模型
    )

    result = completion.choices[0].message.content  # 获取模型生成的文本回答

    if result is None:  # 判断模型是否返回了有效文本
        result = "喵,暂时没有生成回答,请再试一次。"  # 设置空回答时的兜底内容

    if not result.rstrip().endswith("喵"):  # 判断回答结尾是否已经包含“喵”
        result += " 喵~"  # 如果没有,则在回答末尾添加“喵”

    msgs.append({"role": "assistant", "content": result})  # 将 AI 回答保存到上下文列表

    return {"message": result}  # 以 JSON 格式返回回答

if __name__ == "__main__":  # 判断当前文件是否作为主程序运行
    uvicorn.run(app, host="127.0.0.1", port=8000)  # 启动本地服务,监听 8000 端口

这里使用了 ChatRequest 定义请求格式,是为了让 FastAPI 自动解析 JSON 请求体,并对数据进行基本校验。虽然相比原来的写法多了一个类,但这种方式更清晰,也更适合后续开发。

同时,示例在返回回答前检查了结尾是否包含“喵”,以尽量满足角色设定。不过,模型返回内容的具体格式仍可能因服务配置而有所不同。

3.5 配置环境变量

代码中使用了 ARK_API_KEY 和 ARK_MODEL 两个环境变量,分别用于保存 API 密钥和模型标识。

在 Windows 的 PowerShell 中,可以在启动程序前执行:

$env:ARK_API_KEY="替换为你自己的真实密钥"  # 设置当前终端会话中的 API 密钥
$env:ARK_MODEL="替换为你实际使用的模型或推理接入点 ID"  # 设置实际可用的模型标识
python main.py  # 启动 Python 程序

请将代码保存为 main.py,再在 PyCharm 的终端中执行上述命令。

这种方式可以避免将真实密钥直接写入 Python 源文件。不要把真实密钥提交到公开代码仓库或发布在博客中。

四、接口测试

程序成功启动后,在浏览器中打开:

http://127.0.0.1:8000/docs

FastAPI 会自动生成接口文档。在页面中找到 POST /chat,点击 Try it out,在请求体中输入:

{
  "data": "你好,请介绍一下你自己"
}

执行请求后,如果 API 密钥、模型标识、网络连接和接口地址均配置正确,就可以收到类似以下结构的 JSON 响应:

{
  "message": "你好呀!我是可爱的哈吉咪,很高兴认识你!喵~"
}

以上仅为预期的响应格式示例,并非真实接口调用结果。

如果希望使用命令行测试,也可以在 PowerShell 中执行:

curl.exe -X POST "http://127.0.0.1:8000/chat" -H "Content-Type: application/json" -d "{\"data\":\"你好\"}"

如果接口返回 404 Not Found,首先检查请求路径和请求方法是否正确。若接口定义为 @app.post("/chat"),就不能直接通过浏览器地址栏发起普通 GET 请求来调用它。

五、开发过程中需要注意的问题

5.1 接口地址和模型名称必须匹配

不同大模型服务商的接口地址、模型标识和认证方式可能存在差异。即使都支持 OpenAI 兼容 SDK,也不意味着可以直接混用配置。

因此,开发时应确认服务商文档中提供的兼容接口地址、可用模型标识以及 API 密钥配置要求。

5.2 上下文记忆并不等于永久记忆

将消息保存到 msgs 中,只能实现当前程序进程内的简单上下文记忆。如果程序重启,列表会重新初始化。

若需要长期保存聊天记录,可以进一步接入 SQLite、MySQL 等数据库,按照用户 ID 和会话 ID 分别存储消息。

5.3 控制上下文长度

随着对话不断进行,msgs 中的消息会越来越多。每次请求都发送完整历史记录,可能增加 Token 消耗,并受到模型上下文长度的限制。

后续可以通过保留最近若干轮对话、对早期内容进行摘要等方式控制上下文规模。

5.4 处理接口异常

示例代码主要展示核心流程,尚未加入完整的异常处理。在实际使用中,还应考虑网络连接失败、API 密钥无效、调用频率超限、模型服务异常等情况。

同时,应避免在错误日志中打印 API 密钥或其他敏感信息。

六、项目总结与后续优化

通过本次实践,我将 Python、FastAPI 与大语言模型 API 进行了初步结合,完成了一个具备基础对话能力和简单上下文记忆机制的聊天机器人。

项目的核心流程可以概括为:接收用户请求、保存用户消息、调用大模型、获取生成结果、保存 AI 回答,最后将结果返回给用户。

这次开发不仅加深了我对 FastAPI 路由、HTTP 请求、JSON 数据结构和第三方 API 调用的理解,也让我认识到,大模型应用开发除了实现基本功能,还需要关注密钥安全、上下文管理、异常处理和多用户隔离等问题。

后续可以在现有项目基础上继续完善,例如增加多轮会话管理、数据库持久化、流式输出、聊天网页前端以及更完善的错误提示,逐步将简单的聊天脚本扩展为结构更完整的 AI 应用。

对于初学者而言,从一个能够正常运行的聊天机器人入手,再逐步理解每个模块的作用,是学习 Python Web 开发与大模型应用开发的一种有效方式。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐