Week2 day3 OpenAI 大模型 + Gradio 快速搭建交互式对话聊天机器人(对话式 AI)
本案例实现基于 OpenAI 大模型 + Gradio 快速搭建交互式对话聊天机器人(对话式 AI),循序渐进完成开发:从最简单静态返回 → 调用 OpenAI 接口一次性回复 → 流式打字效果输出 → 动态定制系统提示词实现业务场景(服装店导购机器人)。
依赖库:
openai:调用大模型对话接口gradio:快速生成 Web 聊天界面ChatInterfacepython-dotenv:从.env文件安全读取 API 密钥
二、代码演进阶段梳理
阶段 1:最简占位回调(调试 Gradio 接口格式)
python
运行
def chat(message, history): return "bananas" gr.ChatInterface(fn=chat, type="messages").launch()
- 参数说明:
message:用户最新输入消息history:历史对话记录
- 作用:熟悉 Gradio 聊天回调入参结构,不调用大模型,仅测试界面。
阶段 2:拼接历史对话,一次性完整返回 OpenAI 结果
- 格式化
history为 OpenAI 标准消息格式[{"role":"user/assistant", "content":"xxx"}] - 构造完整消息列表:系统提示词 + 历史对话 + 当前用户消息
- 调用接口,一次性获取完整回答直接 return
缺点:响应慢,没有打字流式效果,用户体验差。
阶段 3:流式输出(Stream=True + yield 生成器)
开启
stream=True分片传输模型输出,使用yield逐段推送内容,实现网页实时打字效果,生产聊天机器人主流方案。阶段 4:业务场景增强 —— 动态系统提示词(服装店导购 Bot)
- 基础
system_message设定角色、业务规则:主推打折帽子(6 折),其余商品 5 折,引导客户选购; - 追加规则:鞋子不参与折扣,依然引导看帽子;
- 动态修改系统提示词:检测用户消息包含
belt(皮带),实时追加规则:本店不卖皮带,推荐其他促销商品。
三、核心关键知识点
- 消息结构规范(OpenAI Chat Completions)
json
[ {"role":"system", "content":"角色、规则、指令"}, {"role":"user", "content":"用户消息"}, {"role":"assistant", "content":"AI历史回复"} ]
- Gradio
ChatInterface(type="messages")history 自带标准消息字典数组,需要提取role和content适配 OpenAI; yield生成器函数:实现流式响应,逐块输出文本;- 提示工程应用:
- 角色设定、业务约束
- One-shot Prompting(给出回复示例规范 AI 话术)
- 条件动态修改 system prompt,实现简单业务分支逻辑
四、重点最佳实践(从代码中提炼)
✅ 安全相关
- 密钥不要硬编码
使用
.env+load_dotenv()加载 API Key,禁止直接写在代码内; - 增加密钥存在性判断,方便调试。
✅ 对话构造规范
- 始终把
system_message放在消息列表最前面; - 统一格式化历史对话,保证 role/content 格式兼容 OpenAI;
- 不要直接把原始 history 不经处理传入 API,避免格式报错。
✅ 用户体验
- 优先开启 stream 流式传输 + yield,模拟实时打字,减少等待焦虑;
- 分片处理时增加容错:
chunk.choices[0].delta.content or '',防止空值报错。
✅ Prompt 工程实践
- 将角色、业务约束统一放在 system message,集中管理 AI 行为;
- 使用One-shot 提示:在 system prompt 内提供标准回复范例,规范 AI 输出风格;
- 简单业务分支:可动态拼接 system 提示词,根据用户输入追加临时规则;
⚠️ 局限:复杂分支不建议无限堆砌 system 文本,后续可用工具调用 / 路由逻辑优化。
✅ 代码可维护性
- 模型名称抽为全局常量
MODEL="gpt-4.1-mini",方便统一切换模型; - system_message 单独定义,与业务逻辑解耦;
- 回调函数独立封装,方便迭代调试。
⚠️ 代码现存不足(优化方向)
- 未做输入长度限制,超长对话会造成上下文溢出、费用升高;
- 缺少异常捕获(网络失败、API 限额、接口报错);
- 简单关键词匹配(
'belt' in message.lower())比较简陋,复杂意图识别建议交给大模型自身判断; - 没有会话隔离(多用户共用同一个全局 system_message)。
五、完整可运行整合版参考(汇总所有优化)
python
运行
import os from dotenv import load_dotenv from openai import OpenAI import gradio as gr load_dotenv(override=True) openai_api_key = os.getenv('OPENAI_API_KEY') if openai_api_key: print(f"OpenAI API Key exists and begins {openai_api_key[:8]}") else: print("OpenAI API Key not set") openai = OpenAI() MODEL = 'gpt-4.1-mini' # 系统提示词:服装店导购 system_message = """You are a helpful assistant in a clothes store. You should try to gently encourage the customer to try items that are on sale. Hats are 60% off, and most other items are 50% off. For example, if the customer says 'I'm looking to buy a hat', you could reply something like, 'Wonderful - we have lots of hats - including several that are part of our sales event.' Encourage the customer to buy hats if they are unsure what to get. If the customer asks for shoes, you should respond that shoes are not on sale today, but remind the customer to look at hats!""" def chat(message, history): # 格式化历史对话 history = [{"role":h["role"], "content":h["content"]} for h in history] relevant_system_message = system_message # 动态追加规则:用户询问皮带 if 'belt' in message.lower(): relevant_system_message += " The store does not sell belts; if you are asked for belts, be sure to point out other items on sale." messages = [{"role": "system", "content": relevant_system_message}] + history + [{"role": "user", "content": message}] stream = openai.chat.completions.create(model=MODEL, messages=messages, stream=True) response = "" for chunk in stream: response += chunk.choices[0].delta.content or '' yield response gr.ChatInterface(fn=chat, type="messages").launch()

浙公网安备 33010602011771号