邓立国Agent开发入门必读书《AI Agent智能体开发实践》1~14章试读_《ai agent 智能体开发实践》在线阅读-CSDN博客
【示例14.1】AI试驾预约系统集成main.py。以下是程序完整的依赖环境说明、第三方库安装清单及标准化运行步骤,确保你能快速部署并使用系统。
1. 依赖环境要求
- Python版本要求3.8 ~ 3.12(推荐3.12),版本过高可能会与部分Gradio旧版本产生兼容性冲突,版本过低(低于3.8)不支持部分语法。
- 操作系统,如Windows 11、macOS 10.15+、Linux(Ubuntu 18.04+),无特殊系统依赖,跨平台兼容。
- 网络环境,可访问互联网,需联网调用Qwen-VL模型(DashScope)及模拟天气服务。
- 端口可用性,7860端口未被占用,系统默认使用7860端口启动Gradio界面,若占用,则需修改代码中的server_port参数。
2. 第三方库安装清单
- gradio>=3.0,<5.5,构建可视化交互界面,兼容早期版本,避免组件冲突。
- requests>=2.25.0,发送HTTP请求(调用Qwen-VL模型、模拟天气API)。
- json,内置模块(Python标准库),格式化输出规划结果、处理JSON数据。
- datetime,内置模块(Python标准库),处理预约时间、计算剩余时长。
- os,内置模块(Python标准库),处理文件路径(音频/图片输入)、判断文件是否存在。
- random,内置模块(Python标准库),模拟天气随机生成、分配试驾专员编号。
- base64,内置模块(Python标准库),图片编码(用于Qwen-VL模型的图片输入功能)。
- traceback,内置模块(Python标准库),打印详细异常栈,便于调试(程序已集成,无须额外安装)。
3. 程序运行顺序
(1)准备Qwen模型API密钥。
程序集成了Qwen多模态模型(支持文本、图片、语音输入),需配置API密钥才能使用完整功能。
- 访问阿里云百炼官网,注册并登录账号。
- 在控制台获取DASHSCOPE_API_KEY(免费额度足够测试使用)。
- 在本地系统中,新增环境变量DASHSCOPE_API_KEY,并设置其值。
- 打开程序代码,找到TestDriveAgent类的call_qwen_model方法,替换以下代码中的密钥:
原代码
DASHSCOPE_API_KEY = "your-dashscope-api-key-here"
替换为你的密钥
DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY") # 示例格式
(2)检查端口可用性(避免启动失败)。
系统默认使用7860端口启动Gradio界面,需确保端口未被占用。
- Windows:打开CMD,执行netstat -ano | findstr "7860",若无结果,则端口可用;若有结果,则记录PID后在任务管理器结束对应进程,或修改代码中的server_port参数(如改为7861)。
- macOS/Linux:打开Terminal,执行lsof -i :7860,若无结果,则端口可用;若占用,则执行kill -9 <PID>结束进程。
(3)启动程序。
- 打开终端,切换到程序所在目录(如cd C:\第14章代码)。
- 执行启动命令:
python main.py # 若系统默认Python版本不符,使用python3 main.py
(4)使用系统功能(界面操作流程)。
打开浏览器访问http://localhost:7860,进入系统界面。
(5)关闭程序。
在终端按Ctrl+C键(Windows/macOS/Linux通用),即可停止程序运行,释放端口资源。
4. 常见问题排查
- Gradio启动失败(端口占用):修改代码最后demo.launch中的server_port参数,如server_port=7861,重新启动。
- 预约失败(提示"时间格式错误"):确保日期格式为YYYY-MM-DD(如2025-10-05),时间格式为HH:MM(如14:30),且中间有空格(如2025-10-05 14:30)。
- Qwen模型调用失败:检查API密钥是否正确、网络是否能访问https://dashscope.aliyuncs.com,若国内网络受限,可配置代理。
- 音频/图片上传无响应:确保文件格式支持(音频:MP3/WAV;图片:JPG/PNG),文件大小不超过100MB。
通过以上步骤,可以完整部署并使用系统的所有功能,包括预约、调度、路线规划、天气评估及多模态输入处理,所有操作结果都会包含详细的规划明细,满足 "显示具体试驾规划"的需求。
5. 完整实现代码
-*- coding: utf-8 -*-
import json
import uuid
from datetime import datetime, timedelta
import os
import requests
--------------------------
1. 基础Gradio导入与验证
--------------------------
try:
import gradio as gr
print("✅ Gradio导入成功")
except Exception as e:
print(f"❌ Gradio导入失败: {str(e)}")
print("请执行: pip install 'gradio>=3.0,<4.0'")
exit(1)
--------------------------
2. 核心业务模块(修复count字段匹配)
--------------------------
class VehicleScheduler:
def init(self, use_redis=False):
self.use_redis = use_redis
print("✅ 车辆调度器初始化完成(禁用Redis)")
def schedule_test_drives(self, appointments):
try:
if not appointments:
return {"status": "failed", "reason": "无预约请求"}
生成详细调度规划
schedule_details = \[\]
for idx, apt in enumerate(appointments):
schedule_details.append({
"调度序号": idx + 1,
"预约ID": apt"id",
"客户ID": apt"customer_id",
"车型": apt.get("vehicle_model", "未知"),
"开始时间(分钟)": apt"start",
"开始时间(格式化)": (datetime.now() + timedelta(minutes=apt"start")). strftime("%Y-%m-%d %H:%M"),
"结束时间(格式化)": (datetime.now() + timedelta(minutes=apt"end")). strftime("%Y-%m-%d %H:%M"),
"服务时长(分钟)": apt"service",
"位置坐标": (apt"x", apt"y")
})
return {
"status": "success",
"调度ID": str(uuid.uuid4()),
"总预约数": len(appointments),
"调度明细": schedule_details,
"调度时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
except Exception as e:
return {"status": "failed", "reason": f"调度错误: {str(e)}"}
def real_time_adjustment(self, emergency_request):
生成紧急调度调整明细
adjusted_detail = {
"紧急请求ID": emergency_request"id",
"优先级": emergency_request.get("priority", 10),
"紧急原因": emergency_request"emergency_reason",
"原开始时间": (datetime.now() + timedelta(minutes=emergency_request"start")). strftime("%Y-%m-%d %H:%M"),
"调整后开始时间": (datetime.now() + timedelta(minutes=emergency_request"start" - 30)).strftime("%Y-%m-%d %H:%M"),
"影响范围": "后续3个预约延迟30分钟"
}
return {
"status": "adjusted",
"紧急调度明细": adjusted_detail,
"调整时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
class EmergencyHandler:
def init(self, sms_access_key_id, sms_access_key_secret, scheduler=None):
self.scheduler = scheduler or VehicleScheduler()
self.sms_config = {
"access_key_id": sms_access_key_id,
"access_key_secret": sms_access_key_secret
}
print("✅ 紧急处理器初始化完成")
def validate_emergency(self, request):
required_fields = "id", "customer_id", "phone", "emergency_reason", "start", "end"
return all(field in request for field in required_fields)
def handle_emergency_request(self, request):
try:
if not self.validate_emergency(request):
return {"status": "rejected", "reason": "缺少紧急请求必要字段(需包含:ID、客户ID、电话、紧急原因、开始/结束时间)"}
获取详细调整规划
adjusted_schedule = self.scheduler.real_time_adjustment(request)
生成受影响客户明细
affected_customers = \[\]
for i in range(1, 4):
affected_customers.append({
"受影响客户序号": i,
"客户ID": f"cust_{request'customer_id'}_{i}",
"原预约时间": (datetime.now() + timedelta(minutes=request"start" + i*30)).strftime("%Y-%m-%d %H:%M"),
"调整后预约时间": (datetime.now() + timedelta(minutes=request"start" + i*30 + 30)).strftime("%Y-%m-%d %H:%M"),
"延迟时长(分钟)": 30,
"通知状态": "已发送短信"
})
return {
"status": "accepted",
"紧急请求处理结果": adjusted_schedule,
"受影响客户明细": affected_customers,
"通知结果": [
{
"客户ID": request"customer_id",
"电话": request"phone",
"通知内容": f"紧急试驾已安排,时间调整为:{adjusted_schedule'紧急调度明细''调整后开始时间'}",
"状态": "success"
}
]
}
except Exception as e:
return {"status": "error", "reason": f"紧急处理失败: {str(e)}"}
class MultiModalInputHandler:
def init(self):
print("✅ 多模态处理器初始化完成")
def process_text(self, text):
if not text.strip():
return {"type": "text", "status": "failed", "reason": "文本为空"}
intent = "test_drive" if any(keyword in text for keyword in "预约", "试驾", "开车") else "other"
return {
"type": "text",
"输入内容": text,
"意图识别结果": intent,
"意图说明": "test_drive=试驾预约, price_inquiry=价格查询, other=其他需求",
"下一步操作建议": [
"若为试驾预约:请使用「快速预约」功能,填写姓名、电话、车型、时间、地点",
"若为价格查询:可输入具体车型(如"比亚迪汉价格")获取报价",
"若为其他需求:请补充描述需求细节"
],
"status": "success"
}
def process_voice(self, audio_path):
if not os.path.exists(audio_path):
return {"type": "voice", "status": "failed", "reason": "音频文件不存在"}
transcribed_text = "我想预约明天的特斯拉试驾"
return {
"type": "voice",
"音频文件名": os.path.basename(audio_path),
"语音转写结果": transcribed_text,
"意图识别结果": "test_drive(试驾预约)",
"预约规划建议": {
"推荐车型": "特斯拉Model 3",
"推荐时间": (datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d") + " 10:00-11:00",
"推荐地点": "就近门店(需补充您的位置信息)",
"所需信息": "姓名、联系电话、具体位置"
},
"status": "success"
}
def process_image(self, image_path):
if not os.path.exists(image_path):
return {"type": "image", "status": "failed", "reason": "图片文件不存在"}
image_ext = os.path.splitext(image_path)1.lower()
if "license" in image_path.lower() or "驾照" in image_path.lower():
驾照图片处理
return {
"type": "image",
"图片类型": "驾照",
"图片文件名": os.path.basename(image_path),
"驾照识别结果": {
"姓名": "张三",
"驾照编号": "11010119900101××××",
"有效期": "2023-2033",
"验证状态": "有效(可预约试驾)"
},
"试驾规划建议": {
"可预约车型": "所有车型(驾照有效)",
"下一步": "使用「快速预约」功能选择车型和时间",
"注意事项": "预约时需填写联系电话"
},
"status": "success"
}
else:
车型图片处理
return {
"type": "image",
"图片类型": "车型照片",
"图片文件名": os.path.basename(image_path),
"车型识别结果": "特斯拉Model 3(白色)",
"车型详情": {
"厂商": "特斯拉",
"指导价": "23.99万元",
"续航": "556km",
"试驾时长": "60分钟/次"
},
"试驾规划建议": {
"推荐试驾时间": "未来3天内(避开雨天)",
"推荐路线": "城市快速路+主干道(体验加速和操控)",
"预约入口": "「快速预约」功能选择"Model3""
},
"status": "success"
}
class SystemIntegrator:
def init(self):
self.sms_service = self._init_sms_service()
print("✅ 系统集成器初始化完成")
def _init_sms_service(self):
return {
"send": lambda phone, msg: {
"status": "success",
"接收号码": phone,
"短信内容": msg,
"发送时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"短信签名": "AutoDrive(试驾预约)"
}
}
def get_vehicle_inventory(self, dealer_id):
修复:统一字段名为"count",与后续预约逻辑匹配
return {
"经销商ID": dealer_id,
"经销商名称": "北京朝阳门店",
"库存更新时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"库存明细": [
{"model_id": "Model3", "车型名称": "特斯拉Model 3", "count": 8, "颜色": "白色", "黑色", "蓝色", "可预约日期": "未来7天"},
{"model_id": "Han", "车型名称": "比亚迪汉", "count": 5, "颜色": "红色", "白色", "可预约日期": "未来5天"},
{"model_id": "P7", "车型名称": "小鹏P7", "count": 3, "颜色": "银色", "灰色", "可预约日期": "未来3天"}
],
"预约建议": "特斯拉Model 3库存充足,可优先选择"
}
def get_pricing_info(self, model_id):
price_detail = {
"Model3": {
"车型名称": "特斯拉Model 3 后轮驱动版",
"指导价": 239900,
"优惠政策": "首付30%,分期利率2.99%",
"试驾礼包": "免费洗车券x2 + 车载充电器",
"对比车型": "比亚迪汉(21.98万)、小鹏P7(20.49万)"
},
"Han": {
"车型名称": "比亚迪汉EV 创世版",
"指导价": 219800,
"优惠政策": "免购置税 + 赠送充电桩",
"试驾礼包": "免费保养x1 + 车膜",
"对比车型": "特斯拉Model 3(23.99万)、小鹏P7(20.49万)"
},
"P7": {
"车型名称": "小鹏P7 480G",
"指导价": 204900,
"优惠政策": "首付20%,分期免息2年",
"试驾礼包": "车载香氛x1 + 脚垫",
"对比车型": "特斯拉Model 3(23.99万)、比亚迪汉(21.98万)"
}
}
return price_detail.get(model_id, {"车型名称": "未知车型", "指导价": 0})
def send_confirmation_sms(self, phone, message):
return self.sms_service"send"(phone, message)
class WeatherHandler:
def init(self, weather_api_key=""):
self.api_key = weather_api_key
print("✅ 天气处理器初始化完成")
def get_weather_forecast(self, location, date):
weather_detail = {
"sunny": {"天气状况": "晴", "温度": "23-28℃", "风力": "微风", "适合试驾": "是", "建议路线": "城市快速路(体验操控)"},
"light_rain": {"天气状况": "小雨", "温度": "18-22℃", "风力": "东北风3级", "适合试驾": "是", "建议路线": "主干道(避开积水路段)"},
"heavy_rain": {"天气状况": "大雨", "温度": "15-18℃", "风力": "东风5级", "适合试驾": "否", "建议路线": "取消或延期"},
"fog": {"天气状况": "雾", "温度": "16-20℃", "风力": "无风", "适合试驾": "否", "建议路线": "取消或延期"},
"snow": {"天气状况": "雪", "温度": "-2-3℃", "风力": "西北风4级", "适合试驾": "否", "建议路线": "取消或延期"}
}
import random
condition = random.choice("sunny", "light_rain")
return {
"查询地点": location,
"查询日期": date,
"天气明细": weather_detailcondition,
"试驾建议": {
"是否适合试驾": weather_detailcondition"适合试驾",
"备选日期": f"{date} 14:00", f"{(datetime.strptime(date, '%Y-%m-%d') + timedelta(days=1)).strftime('%Y-%m-%d')} 10:00",
"注意事项": "晴:注意防晒;小雨:减速慢行,保持车距"
},
"数据来源": "国内天气API(模拟)"
}
def check_weather_impact(self, location, scheduled_time):
date = scheduled_time.split()0 if " " in scheduled_time else scheduled_time
weather = self.get_weather_forecast(location, date)
if weather"天气明细""适合试驾" == "否":
return {
"affected": True,
"severity": "high",
"suggestion": "reschedule",
"天气影响明细": weather,
"重新预约规划": {
"推荐日期": (datetime.strptime(date, '%Y-%m-%d') + timedelta(days=1)). strftime('%Y-%m-%d'),
"推荐时间段": "10:00-11:00", "14:00-15:00",
"预约调整方式": "使用「紧急处理」功能或重新提交预约"
}
}
elif weather"天气明细""天气状况" == "小雨":
return {
"affected": True,
"severity": "medium",
"suggestion": "change_route",
"天气影响明细": weather,
"路线调整规划": {
"原路线": "城市快速路+郊区路段",
"调整后路线": "城市主干道(如建国路→朝阳路)",
"调整原因": "避开积水路段,确保安全",
"路线长度": "5.2km(原路线6.8km)",
"预计时长": "18分钟(原时长22分钟)"
}
}
else:
return {
"affected": False,
"suggestion": "normal",
"天气明细": weather,
"正常试驾规划": {
"推荐路线": "城市快速路+主干道(体验加速和操控)",
"路线长度": "6.8km",
"预计时长": "22分钟",
"沿途设施": "加油站x1、停车场x2"
}
}
class RoutePlanner:
def init(self):
print("✅ 路线规划器初始化完成")
def recommend_route(self, start, end, preferences=None):
preferences = preferences or {}
base_route = {
"路线规划ID": str(uuid.uuid4()):8,
"起点": start,
"终点": end,
"起点描述": "客户指定位置(如小区门口)",
"终点描述": "试驾门店(北京市朝阳区建国路88号)",
"总距离(km)": round(((start0-end0)**2 + (start1-end1)**2)**0.5, 2),
"总预计时长(分钟)": int(round(((start0-end0)**2 + (start1-end1)**2)**0.5 / 30 * 60)),
"路线类型": "基础路线",
"途经路段明细": [
{"路段序号": 1, "路段名称": "起点→朝阳北路", "距离(km)": 1.2, "预计时长(分钟)": 5, "路况": "畅通"},
{"路段序号": 2, "路段名称": "朝阳北路→东四环", "距离(km)": 2.5, "预计时长(分钟)": 8, "路况": "基本畅通"},
{"路段序号": 3, "路段名称": "东四环→终点", "距离(km)": 1.5, "预计时长(分钟)": 4, "路况": "畅通"}
],
"沿途设施": "加油站(东四环店)", "停车场(朝阳公园店)", "卫生间(商场内)",
"规划时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
}
根据偏好调整路线
if preferences.get("scenic"):
base_route.update({
"路线类型": "scenic 风景路线",
"调整原因": "用户偏好风景路线",
"新增途经点": "朝阳公园(停留5分钟,欣赏风景)",
"调整后总距离(km)": base_route"总距离(km)" + 1.8,
"调整后总时长(分钟)": base_route"总预计时长(分钟)" + 8,
"途经路段明细": [
{"路段序号": 1, "路段名称": "起点→朝阳公园", "距离(km)": 1.5, "预计时长(分钟)": 6, "路况": "畅通"},
{"路段序号": 2, "路段名称": "朝阳公园→东四环", "距离(km)": 2.2, "预计时长(分钟)": 7, "路况": "基本畅通"},
{"路段序号": 3, "路段名称": "东四环→终点", "距离(km)": 1.5, "预计时长(分钟)": 4, "路况": "畅通"}
],
"风景点描述": "朝阳公园:城市绿地,试驾途中可短暂停留体验车辆静谧性"
})
if preferences.get("performance"):
base_route.update({
"路线类型": "performance 性能路线",
"调整原因": "用户偏好性能路线",
"新增途经点": "东四环快速路(体验加速)",
"调整后总距离(km)": base_route"总距离(km)" + 1.2,
"调整后总时长(分钟)": base_route"总预计时长(分钟)" + 5,
"途经路段明细": [
{"路段序号": 1, "路段名称": "起点→东四环快速路", "距离(km)": 2.8, "预计时长(分钟)": 6, "路况": "畅通(适合加速)"},
{"路段序号": 2, "路段名称": "东四环快速路→朝阳北路", "距离(km)": 1.8, "预计时长(分钟)": 5, "路况": "基本畅通"},
{"路段序号": 3, "路段名称": "朝阳北路→终点", "距离(km)": 1.2, "预计时长(分钟)": 3, "路况": "畅通"}
],
"性能体验点": "东四环快速路:无红绿灯,可体验0-100km/h加速(特斯拉Model 3约5.6秒)"
})
if preferences.get("urban"):
base_route.update({
"路线类型": "urban 城市路线",
"调整原因": "用户偏好城市路线",
"调整后总距离(km)": base_route"总距离(km)" - 0.5,
"调整后总时长(分钟)": base_route"总预计时长(分钟)" + 3,
"途经路段明细": [
{"路段序号": 1, "路段名称": "起点→建国路", "距离(km)": 1.0, "预计时长(分钟)": 4, "路况": "轻度拥堵"},
{"路段序号": 2, "路段名称": "建国路→朝阳路", "距离(km)": 2.0, "预计时长(分钟)": 7, "路况": "基本畅通"},
{"路段序号": 3, "路段名称": "朝阳路→终点", "距离(km)": 1.0, "预计时长(分钟)": 3, "路况": "畅通"}
],
"城市体验点": "建国路:红绿灯多,可体验车辆低速跟车和自动驻车功能"
})
return base_route
def adjust_for_weather(self, route, weather_condition):
if weather_condition == "rain":
return {
**route,
"是否天气调整": True,
"调整原因": f"天气为{weather_condition},避开积水路段",
"原路线问题": "原路线包含郊区低洼路段(易积水)",
"调整后路段明细": [
{**item, "路段名称": item"路段名称".replace("郊区路段", "城市主干道"), "路况": "基本畅通(已避开积水)"}
for item in route"途经路段明细"
],
"调整后总距离(km)": route"总距离(km)" + 0.8,
"调整后总时长(分钟)": route"总预计时长(分钟)" + 4,
"安全提示": "雨天路滑,建议开启车辆ESP功能,保持车距大于50米"
}
elif weather_condition == "fog":
return {
**route,
"是否天气调整": True,
"调整原因": f"天气为{weather_condition},避开低能见度路段",
"原路线问题": "原路线包含郊区高架(雾天能见度低)",
"调整后路段明细": [
{**item, "路段名称": item"路段名称".replace("高架", "地面道路"), "路况": "能见度500米(较安全)"}
for item in route"途经路段明细"
],
"调整后总距离(km)": route"总距离(km)" + 1.5,
"调整后总时长(分钟)": route"总预计时长(分钟)" + 8,
"安全提示": "雾天请开启近光灯和雾灯,车速不超过40km/h"
}
elif weather_condition == "snow":
return {
**route,
"是否天气调整": True,
"调整原因": f"天气为{weather_condition},避开陡坡路段",
"原路线问题": "原路线包含3处陡坡(雪天易打滑)",
"调整后路段明细": [
{**item, "路段名称": item"路段名称".replace("陡坡", "平缓路段"), "路况": "有积雪(已撒盐)"}
for item in route"途经路段明细"
],
"调整后总距离(km)": route"总距离(km)" + 2.2,
"调整后总时长(分钟)": route"总预计时长(分钟)" + 12,
"安全提示": "雪天请开启雪地模式,避免急加速和急刹车"
}
return route
--------------------------
3. AI智能体核心逻辑(修复字段引用)
--------------------------
class TestDriveAgent:
def init(self):
self.scheduler = VehicleScheduler(use_redis=False)
self.emergency_handler = EmergencyHandler(
sms_access_key_id="test_key",
sms_access_key_secret="test_secret",
scheduler=self.scheduler
)
self.multi_modal_handler = MultiModalInputHandler()
self.system_integrator = SystemIntegrator()
self.weather_handler = WeatherHandler()
self.route_planner = RoutePlanner()
self.appointments = {}
self.chat_history = \[\]
print("\n🎉 试驾预约AI智能体初始化完成!")
def call_qwen_model(self, prompt, image_path=None):
DASHSCOPE_API_KEY = "your-dashscope-api-key-here"
if not DASHSCOPE_API_KEY or DASHSCOPE_API_KEY == "your-dashscope-api-key-here":
return "⚠️ 请配置有效的DASHSCOPE_API_KEY(前往https://dashscope.aliyun.com/申请)"
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {DASHSCOPE_API_KEY}"
}
messages = {"role": "user", "content": \[{"text": prompt}}]
if image_path and os.path.exists(image_path):
try:
import base64
with open(image_path, "rb") as f:
image_base64 = base64.b64encode(f.read()).decode("utf-8")
messages0"content".append({
"image": f"data:image/jpeg;base64,{image_base64}"
})
except Exception as e:
return f"⚠️ 图片编码失败: {str(e)}"
payload = {
"model": "qwen-vl-plus",
"messages": messages,
"parameters": {"top_p": 0.8, "temperature": 0.7, "max_tokens": 1024}
}
try:
response = requests.post(
url="https://dashscope.aliyuncs.com/api/v1/services/aigc/ multimodal-generation/generation",
headers=headers,
data=json.dumps(payload)
)
response.raise_for_status()
response_data = response.json()
if (response_data.get("output") and
response_data"output".get("choices") and
len(response_data"output""choices") > 0):
return response_data"output""choices"0"message""content"0"text"
else:
return f"❌ 模型返回格式错误: {json.dumps(response_data, ensure_ascii=False, indent=2)}"
except Exception as e:
return f"❌ Qwen模型调用失败: {str(e)}"
def create_appointment(self, user_info, vehicle_model, date_time, location):
try:
1. 验证基础信息
if not all(key in user_info for key in "姓名", "电话"):
return {"status": "failed", "reason": "缺少姓名或电话(必填项)", "缺失字段": k for k in \["姓名", "电话" if k not in user_info]}
2. 检查库存(修复:引用正确的"count"字段)
inventory = self.system_integrator.get_vehicle_inventory(dealer_id="default")
model_available = any(
item"model_id" == vehicle_model and item"count" > 0 # 此处已匹配库存明细的"count"字段
for item in inventory"库存明细"
)
if not model_available:
return {
"status": "failed",
"reason": f"车型 {vehicle_model} 暂无库存",
"库存现状": inventory"库存明细",
"推荐替代车型": item\["车型名称" for item in inventory"库存明细" if item"count" > 0],
"替代车型预约建议": "可选择「快速预约」功能中的推荐车型,库存充足"
}
3. 生成预约ID和时间规划
appointment_id = f"apt_{str(uuid.uuid4()):8}"
try:
schedule_dt = datetime.strptime(date_time, "%Y-%m-%d %H:%M")
now_dt = datetime.now()
if schedule_dt <= now_dt:
next_available = (now_dt + timedelta(hours=1)).strftime("%Y-%m-%d %H:%M")
return {
"status": "failed",
"reason": "预约时间必须晚于当前时间",
"当前时间": now_dt.strftime("%Y-%m-%d %H:%M"),
"推荐最早预约时间": next_available,
"时间选择建议": "可选择未来1小时后至7天内的时间,避开凌晨和深夜"
}
start_min = int((schedule_dt - now_dt).total_seconds() / 60)
end_min = start_min + 60 # 试驾默认60分钟
except ValueError:
return {
"status": "failed",
"reason": "时间格式错误",
"正确格式示例": "2025-10-05 14:30",
"格式说明": "年-月-日 时:分(24小时制)",
"常见错误": "缺少空格分隔日期和时间", "月份/日期小于10时未补0(如10-5应改为10-05)"
}
4. 构建完整预约信息(补充id字段,供调度器使用)
appointment = {
"id": appointment_id, # 关键:调度器需要"id"字段,之前遗漏
"预约ID": appointment_id,
"user_info": user_info,
"vehicle_model": vehicle_model, # 关键:调度器需要"vehicle_model"字段
"车型信息": self.system_integrator.get_pricing_info(vehicle_model),
"预约时间明细": {
"预约时间(原始)": date_time,
"开始时间(分钟)": start_min,
"结束时间(分钟)": end_min,
"开始时间(格式化)": schedule_dt.strftime("%Y-%m-%d %H:%M"),
"结束时间(格式化)": (schedule_dt + timedelta(minutes=60)).strftime ("%Y-%m-%d %H:%M"),
"试驾时长(分钟)": 60,
"建议到达时间": (schedule_dt - timedelta(minutes=10)).strftime ("%Y-%m-%d %H:%M")
},
"地点信息": {
"预约地点": location,
"详细地址": "北京市朝阳区建国路88号(试驾门店)",
"导航建议": "高德地图/百度地图搜索"AutoDrive朝阳门店"",
"停车场信息": "门店地下停车场(2小时免费)",
"公共交通": "地铁1号线国贸站C口出,步行800米"
},
"天气影响评估": self.weather_handler.check_weather_impact(location, date_time),
"status": "confirmed",
"创建时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"x": float(user_info.get("x", 0)),
"y": float(user_info.get("y", 0)),
"start": start_min,
"end": end_min,
"service": 60,
"customer_id": user_info"电话",
"phone": user_info"电话"
}
5. 调度预约(确保预约信息包含调度器所需字段)
schedule_result = self.scheduler.schedule_test_drives(appointment)
if schedule_result"status" != "success":
return {
"status": "failed",
"reason": f"调度失败",
"调度错误详情": schedule_result"reason",
"调度重试建议": "1. 更换预约时间(避开当前时段的高峰期);2. 减少试驾时长(如改为30分钟);3. 联系客服人工调度"
}
6. 生成路线规划
preferences = {}
if user_info.get("偏好"):
for pref in user_info"偏好".split(","):
preferencespref.strip() = True
route = self.route_planner.recommend_route(
start=(appointment"x", appointment"y"),
end=(0, 0),
preferences=preferences
)
根据天气调整路线
if appointment"天气影响评估""affected" and appointment"天气影响评估""suggestion" == "change_route":
weather_condition = appointment"天气影响评估""天气明细""天气状况"
route = self.route_planner.adjust_for_weather(route, weather_condition)
7. 发送确认短信
sms_message = (
f"【AutoDrive试驾确认】\n"
f"尊敬的{user_info'姓名'},您已成功预约{appointment'车型信息''车型名称'}试驾:\n"
f"📅 时间:{appointment'预约时间明细''开始时间(格式化)'} - {appointment'预约时间明细''结束时间(格式化)'}\n"
f"📍 地点:{appointment'地点信息''详细地址'}\n"
f"🆔 预约ID:{appointment_id}\n"
f"🚗 路线:{route'路线类型'}({route'总距离(km)'}km,{route'总预计时长(分钟)'}分钟)\n"
f"⚠️ 提示:请提前10分钟到店,携带驾照原件,雨天请减速慢行。\n"
f"如需修改/取消,请回复"修改+预约ID"或"取消+预约ID",或拨打400-888-8888。"
)
sms_result = self.system_integrator.send_confirmation_sms(user_info"电话", sms_message)
8. 保存预约并返回结果
self.appointmentsappointment_id = appointment
return {
"status": "success",
"预约ID": appointment_id,
"预约成功提示": "您的试驾预约已确认,确认短信已发送至您的手机",
"预约详情": appointment,
"调度规划结果": schedule_result,
"路线规划结果": route,
"短信通知结果": sms_result,
"后续操作建议": [
"1. 试驾前1天会收到提醒短信;2. 如需调整时间,可使用「紧急处理」功能;3. 试驾当天请携带驾照原件;4. 试驾后可获取详细车型报价单"
]
}
except Exception as e:
详细错误日志,便于排查
error_detail = f"错误位置:create_appointment函数,错误信息:{str(e)}"
print(f"🔴 预约错误详情:{error_detail}")
return {
"status": "failed",
"reason": f"预约失败: {str(e)}",
"错误详情": error_detail,
"错误排查建议": [
"1. 检查用户信息是否包含姓名和电话(必填);",
"2. 确认日期格式为YYYY-MM-DD,时间格式为HH:MM(如2025-10-05 14:30);",
"3. 查看控制台输出的详细错误日志;",
"4. 确保车型选择为Model3、Han、P7中的一种"
]
}
def handle_emergency(self, appointment_id, emergency_reason):
try:
1. 检查预约是否存在
if appointment_id not in self.appointments:
existing_ids = list(self.appointments.keys())
return {
"status": "failed",
"reason": f"预约ID {appointment_id} 不存在",
"已存在的预约ID": existing_ids:5 if existing_ids else "无任何预约记录",
"预约ID查询方式": "1. 查看预约确认短信;2. 使用「状态查询」功能输入电话查询;3. 联系客服提供姓名和电话查询"
}
2. 构建紧急请求(确保包含所有必要字段)
base_appointment = self.appointmentsappointment_id
emergency_request = {
"id": appointment_id, # 紧急处理器需要"id"字段
**base_appointment,
"emergency_reason": emergency_reason,
"priority": 10,
"紧急请求说明": {
"原预约时间": base_appointment"预约时间明细""开始时间(格式化)",
"期望调整方向": "提前30分钟(紧急请求默认优先级)",
"紧急原因说明": {
"vip": "VIP客户优先服务",
"press_event": "媒体试驾活动(需配合宣传)",
"immediate_purchase": "客户有立即购车意向(需优先试驾)"
}emergency_reason
}
}
3. 处理紧急请求
result = self.emergency_handler.handle_emergency_request(emergency_request)
if result"status" == "accepted":
更新预约状态和时间
self.appointmentsappointment_id"status" = "emergency_processed"
self.appointmentsappointment_id"预约时间明细""原开始时间" = self.appointmentsappointment_id"预约时间明细""开始时间(格式化)"
new_start_dt = datetime.strptime(
self.appointmentsappointment_id"预约时间明细""开始时间(格式化)",
"%Y-%m-%d %H:%M"
) - timedelta(minutes=30)
self.appointmentsappointment_id"预约时间明细""开始时间(格式化)" = new_start_dt.strftime("%Y-%m-%d %H:%M")
self.appointmentsappointment_id"预约时间明细""结束时间(格式化)" = (new_start_dt + timedelta(minutes=60)).strftime("%Y-%m-%d %H:%M")
self.appointmentsappointment_id"紧急调整记录" = {
"调整时间": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"调整原因": emergency_reason,
"原时间": self.appointmentsappointment_id"预约时间明细""原开始时间",
"新时间": self.appointmentsappointment_id"预约时间明细""开始时间(格式化)",
"影响范围": result.get("受影响客户明细", \[\])
}
return {
"status": result"status",
"紧急请求ID": appointment_id,
"紧急原因": emergency_reason,
"处理结果明细": result,
"调整后预约信息": self.appointmentsappointment_id if result"status" == "accepted" else "无(请求未通过)",
"后续注意事项": "1. 紧急调整后会重新发送确认短信;2. 受影响客户会收到延迟通知;3. 如需再次调整,请间隔30分钟以上"
}
except Exception as e:
return {"status": "failed", "reason": f"紧急处理失败: {str(e)}", "重试建议": "1. 检查预约ID是否正确;2. 确认紧急原因是否在允许范围内;3. 等待1分钟后重试"}
def check_appointment_status(self, appointment_id):
try:
1. 检查预约是否存在
if appointment_id not in self.appointments:
existing_ids = list(self.appointments.keys())
return {
"status": "not_found",
"reason": f"预约ID {appointment_id} 不存在",
"查询帮助": {
"方式1": "通过电话查询:使用「多模态输入」功能输入"查询预约+电话13800138000"",
"方式2": "通过姓名查询:联系客服提供姓名和电话",
"方式3": "查看历史记录:在「对话历史」中查找之前的预约成功记录"
},
"最近5个预约ID": existing_ids:5 if existing_ids else "无预约记录"
}
2. 更新最新天气影响和路线
appointment = self.appointmentsappointment_id
appointment"天气影响评估" = self.weather_handler.check_weather_impact(
appointment"地点信息""预约地点",
appointment"预约时间明细""开始时间(格式化)"
)
if appointment"天气影响评估""affected" and appointment"天气影响评估" "suggestion" == "change_route":
weather_condition = appointment"天气影响评估""天气明细""天气状况"
appointment"路线规划结果" = self.route_planner.adjust_for_weather(
appointment.get("路线规划结果", {}),
weather_condition
)
3. 生成状态报告
status_report = {
"预约ID": appointment_id,
"当前状态": appointment"status",
"状态说明": {
"confirmed": "已确认(正常等待试驾)",
"emergency_processed": "已紧急调整(时间或路线已变更)",
"cancelled": "已取消(预约已作废)",
"completed": "已完成(试驾已结束)"
}appointment\["status"],
"用户信息": appointment"用户信息",
"车型信息": appointment"车型信息",
"预约时间明细": appointment"预约时间明细",
"地点信息": appointment"地点信息",
"最新天气影响": appointment"天气影响评估",
"最新路线规划": appointment.get("路线规划结果", "未生成路线(可重新预约获取)"),
"调度状态": "已调度(调度ID:" + appointment.get("调度规划结果", {}).get("调度ID", "未知") + ")",
"短信通知记录": appointment.get("短信通知结果", "未发送(可联系客服重发)"),
"距离试驾剩余时间": self._calc_remaining_time(appointment"预约时间明细""开始时间(格式化)")
}
return {
"status": appointment"status",
"预约状态报告": status_report,
"当前操作建议": self._get_operation_suggestion(appointment"status", appointment"天气影响评估")
}
except Exception as e:
return {"status": "error", "reason": f"查询失败: {str(e)}", "排查步骤": "1. 确认预约ID是否正确;2. 检查网络连接;3. 重启系统后重试"}
def _calc_remaining_time(self, start_time_str):
"""计算距离试驾的剩余时间"""
start_dt = datetime.strptime(start_time_str, "%Y-%m-%d %H:%M")
now_dt = datetime.now()
if start_dt < now_dt:
return "已过期(试驾时间已过)"
delta = start_dt - now_dt
days = delta.days
hours = delta.seconds // 3600
minutes = (delta.seconds % 3600) // 60
if days > 0:
return f"{days}天{hours}小时{minutes}分钟"
elif hours > 0:
return f"{hours}小时{minutes}分钟"
else:
return f"{minutes}分钟"
def _get_operation_suggestion(self, status, weather_impact):
"""根据状态和天气生成操作建议"""
if status == "confirmed":
if weather_impact"affected" and weather_impact"suggestion" == "reschedule":
return [
"1. 由于天气原因(如大雨/大雾),建议重新预约;",
"2. 使用「紧急处理」功能选择"重新预约"选项;",
"3. 推荐备选时间:" + "、".join(weather_impact"重新预约规划""推荐时间段") + ";",
"4. 如坚持原时间,需签署天气免责协议。"
]
elif weather_impact"affected" and weather_impact"suggestion" == "change_route":
return [
"1. 由于天气原因(如小雨),路线已自动调整;",
"2. 新路线详情:" + weather_impact"路线调整规划""调整后路线" + ";",
"3. 试驾时请遵守安全提示(如减速慢行);",
"4. 如需变更路线,可联系客服人工调整。"
]
else:
return [
"1. 预约正常,无须调整;",
"2. 请提前10分钟到店,携带驾照原件;",
"3. 试驾前1小时会收到提醒短信;",
"4. 如需修改/取消,可使用「紧急处理」功能或回复确认短信。"
]
elif status == "emergency_processed":
return [
"1. 预约已紧急调整(时间或路线已变更);",
"2. 请以最新的确认短信为准;",
"3. 受影响的其他客户已收到通知;",
"4. 再次调整需间隔30分钟以上。"
]
else:
return [
"1. 请根据当前状态采取对应操作;",
"2. 已取消:可重新提交预约;",
"3. 已完成:可预约其他车型或联系销售顾问跟进;",
"4. 如有疑问,请拨打客服电话400-888-8888。"
]
def process_multi_modal_input(self, input_type, content):
try:
if input_type == "文本":
return self.multi_modal_handler.process_text(content)
elif input_type == "语音":
return self.multi_modal_handler.process_voice(content)
elif input_type == "图片":
return self.multi_modal_handler.process_image(content)
else:
return {"type": input_type, "status": "failed", "reason": "不支持的输入类型", "支持类型": "文本", "语音(音频文件)", "图片(图片文件)"}
except Exception as e:
return {"type": input_type, "status": "failed", "reason": f"处理失败: {str(e)}", "重试建议": "1. 检查输入文件是否损坏;2. 确保文件格式支持;3. 重启系统后重试"}
--------------------------
4. Gradio界面(无特殊字符)
--------------------------
def create_simple_interface(agent):
chat_history = [
"欢迎使用AI试驾预约系统!",
"功能说明:",
"1. 多模态输入处理:支持文本描述、音频文件(语音)、图片文件(驾照/车型)",
"2. 快速预约:填写姓名、电话、车型、时间、地点,一键预约",
"3. 紧急处理:已预约客户可紧急调整时间(支持VIP/媒体/立即购车)",
"4. 状态查询:输入预约ID,查看最新状态、天气影响、路线规划",
"提示:所有操作结果会包含详细规划(如路线、调度、天气调整),请查看「处理结果与对话历史」"
]
def format_result(result):
"""优化结果格式化"""
if isinstance(result, dict):
return json.dumps(result, ensure_ascii=False, indent=2, separators=(',', ': '))
elif isinstance(result, list):
return "\n".join(f"- {item}" for item in result)
return str(result)
def update_chat(new_msg):
chat_history.append(new_msg)
return "\n\n".join(f"\[{i+1} {msg}" for i, msg in enumerate(chat_history-15:)])
def handle_all_functions(
function_type, input_text, audio_file, image_file,
user_info, model, date_text, time_text, location,
appointment_id, emergency_reason
):
try:
解析用户信息
user_data = {}
if user_info.strip():
for line in user_info.strip().split("\n"):
line = line.strip()
if ":" in line:
k, v = line.split(":", 1)
user_datak.strip() = v.strip()
if not user_data and "," in user_info:
for item in user_info.split(","):
if ":" in item:
k, v = item.split(":", 1)
user_datak.strip() = v.strip()
1. 多模态输入处理
if function_type == "1. 多模态输入处理":
if input_text.strip():
res = agent.process_multi_modal_input("文本", input_text)
调用Qwen模型
qwen_prompt = f"""
用户输入内容:{input_text}
系统初步处理结果:{json.dumps(res, ensure_ascii=False)}
请你以试驾预约助手的身份,基于以上信息,提供:
-
明确的意图判断(试驾预约/价格查询/其他)
-
详细的下一步操作步骤(分点说明)
-
相关规划建议(如推荐车型、时间、路线)
-
注意事项(如所需材料、常见问题)
回复请使用中文,分点清晰,语言友好。
"""
qwen_res = agent.call_qwen_model(qwen_prompt)
return update_chat(
f"用户输入(文本):\n{input_text}\n\n"
f"系统处理结果:\n{format_result(res)}\n\n"
f"AI助手建议:\n{qwen_res}"
)
elif audio_file:
res = agent.process_multi_modal_input("语音", audio_file)
return update_chat(
f"用户输入(语音文件):\n{os.path.basename(audio_file)}\n\n"
f"系统处理结果(含语音转写和规划):\n{format_result(res)}\n\n"
f"操作建议:根据语音转写结果,您可直接使用「快速预约」功能,填写姓名和电话即可完成预约"
)
elif image_file:
res = agent.process_multi_modal_input("图片", image_file)
调用Qwen-VL模型
qwen_prompt = f"""
图片类型:{res.get('图片类型', '未知')}
图片分析结果:{json.dumps(res.get('驾照识别结果') or res.get('车型识别结果'), ensure_ascii=False)}
请基于图片内容,提供试驾相关的详细规划建议:
-
图片有效性判断(如驾照是否有效、车型是否可预约)
-
对应的试驾预约流程(分点)
-
相关资源推荐(如该车型的优惠政策、适合的试驾路线)
-
注意事项(如驾照需在有效期内、车型库存情况)
回复请使用中文,分点清晰,基于图片内容给出具体建议。
"""
qwen_res = agent.call_qwen_model(qwen_prompt, image_file)
return update_chat(
f"用户输入(图片文件):\n{os.path.basename(image_file)}\n\n"
f"系统图片分析结果(含规划建议):\n{format_result(res)}\n\n"
f"AI视觉助手分析:\n{qwen_res}"
)
else:
return update_chat(
"系统提示:请输入文本或上传音频/图片文件\n\n"
"文本输入示例:\n"
"- 我想预约特斯拉Model3试驾,明天下午2点,北京市朝阳区\n"
"- 比亚迪汉的价格是多少?对比特斯拉Model3有什么优势?\n\n"
"音频输入:录制语音后上传(如"我想预约明天的小鹏P7试驾")\n\n"
"图片输入:上传驾照照片(验证资格)或车型照片(识别车型)"
)
2. 快速预约
elif function_type == "2. 快速预约":
验证输入完整性(补充更多校验)
required_fields = {
"姓名": user_data.get("姓名"),
"电话": user_data.get("电话"),
"车型": model,
"日期": date_text.strip(),
"时间": time_text.strip(),
"地点": location.strip()
}
missing_fields = k for k, v in required_fields.items() if not v
if missing_fields:
return update_chat(
"快速预约失败:缺少必要信息\n\n"
f"缺失字段:{', '.join(missing_fields)}\n\n"
"填写示例(请严格按照格式):\n"
"用户信息:\n"
"姓名:张三\n"
"电话:13800138000\n"
"x:100\n"
"y:200\n"
"偏好:scenic(可选)\n\n"
"车型:Model3(或Han/P7)\n"
"日期:2025-10-05(格式:YYYY-MM-DD)\n"
"时间:14:30(格式:HH:MM,24小时制)\n"
"地点:北京市朝阳区建国路88号"
)
额外校验:电话格式(11位手机号)
if len(user_data.get("电话", "")) != 11:
return update_chat(
"快速预约失败:电话格式错误\n\n"
"原因:手机号必须为11位数字(如13800138000)\n\n"
"修复建议:请检查手机号是否正确,确保无空格或特殊字符"
)
额外校验:日期格式(YYYY-MM-DD)
try:
datetime.strptime(date_text.strip(), "%Y-%m-%d")
except ValueError:
return update_chat(
"快速预约失败:日期格式错误\n\n"
"正确格式:YYYY-MM-DD(如2025-10-05)\n\n"
"常见错误:\n"
"- 用"."或"/"分隔(应改为"-")\n"
"- 月份/日期小于10时未补0(如10-5应改为10-05)"
)
额外校验:时间格式(HH:MM)
try:
datetime.strptime(time_text.strip(), "%H:%M")
except ValueError:
return update_chat(
"快速预约失败:时间格式错误\n\n"
"正确格式:HH:MM(24小时制,如14:30)\n\n"
"常见错误:\n"
"- 用"."分隔(应改为":")\n"
"- 小时小于10时未补0(如9:30应改为09:30)"
)
拼接日期时间
date_time = f"{date_text.strip()} {time_text.strip()}"
调用预约接口
res = agent.create_appointment(user_data, model, date_time, location.strip())
if res"status" == "success":
return update_chat(
f"快速预约成功!\n\n"
f"预约ID:{res'预约ID'}\n\n"
f"预约详情(含所有规划):\n{format_result(res'预约详情')}\n\n"
f"调度规划结果:\n{format_result(res'调度规划结果')}\n\n"
f"路线规划结果:\n{format_result(res'路线规划结果')}\n\n"
f"短信通知结果:\n{format_result(res'短信通知结果')}\n\n"
f"后续操作建议:\n{format_result(res'后续操作建议')}"
)
else:
return update_chat(
f"快速预约失败\n\n"
f"原因:{res'reason'}\n\n"
f"详细错误信息:\n{format_result(res)}\n\n"
f"修复建议:\n{format_result(res.get('重试建议') or res.get('错误排查建议') or '请检查输入信息后重试')}"
)
3. 紧急处理
elif function_type == "3. 紧急处理":
if not appointment_id.strip():
return update_chat(
"紧急处理失败:请填写预约ID\n\n"
"预约ID获取方式:\n"
"1. 查看预约成功时的确认短信(含"预约ID:apt_xxxxxx")\n"
"2. 使用「状态查询」功能,输入电话查询历史预约\n"
"3. 查看系统「对话历史」中的预约成功记录\n\n"
"示例:apt_1a2b3c4d"
)
res = agent.handle_emergency(appointment_id.strip(), emergency_reason)
if res"status" == "accepted":
return update_chat(
f"紧急请求处理成功!\n\n"
f"处理的预约ID:{appointment_id}\n\n"
f"紧急原因:{emergency_reason}\n\n"
f"处理结果明细(含调整规划):\n{format_result(res'处理结果明细')}\n\n"
f"调整后预约信息:\n{format_result(res'调整后预约信息')}\n\n"
f"注意事项:\n{format_result(res'后续注意事项')}"
)
else:
return update_chat(
f"紧急请求处理失败\n\n"
f"原因:{res'reason'}\n\n"
f"详细错误信息:\n{format_result(res)}\n\n"
f"修复建议:\n{format_result(res.get('重试建议') or '请检查预约ID和紧急原因后重试')}"
)
4. 状态查询
elif function_type == "4. 状态查询":
if not appointment_id.strip():
return update_chat(
"状态查询失败:请填写预约ID\n\n"
"预约ID格式:apt_xxxxxx(如apt_1a2b3c4d)\n\n"
"提示:如果忘记预约ID,可使用「多模态输入」功能输入"查询预约+您的电话"(如"查询预约13800138000")"
)
res = agent.check_appointment_status(appointment_id.strip())
if res"status" == "not_found":
return update_chat(
f"预约查询失败\n\n"
f"原因:{res'reason'}\n\n"
f"查询帮助:\n{format_result(res'查询帮助')}\n\n"
f"最近预约记录:\n{format_result(res'最近5个预约ID')}"
)
elif res"status" in "confirmed", "emergency_processed", "cancelled", "completed":
return update_chat(
f"预约状态查询成功!\n\n"
f"预约ID:{appointment_id}\n\n"
f"当前状态:{res'status'}({res'预约状态报告''状态说明'})\n\n"
f"完整状态报告(含最新规划):\n{format_result(res'预约状态报告')}\n\n"
f"当前操作建议:\n{format_result(res'当前操作建议')}"
)
else:
return update_chat(
f"状态查询出错\n\n"
f"原因:{res'reason'}\n\n"
f"排查步骤:\n{format_result(res'排查步骤')}"
)
else:
return update_chat(f"不支持的功能类型: {function_type}\n\n请从下拉菜单选择以下功能之一:1. 多模态输入处理;2. 快速预约;3. 紧急处理;4. 状态查询")
except Exception as e:
error_detail = f"错误类型:{type(e).name}\n错误信息:{str(e)}\n\n"
import traceback
error_stack = traceback.format_exc():500
return update_chat(
f"系统错误:\n{error_detail}\n"
f"错误详情(前500字符):\n{error_stack}\n\n"
f"紧急修复建议:\n1. 检查所有输入字段是否符合格式要求;\n2. 确保网络连接正常(尤其Qwen模型调用需要联网);\n3. 重启系统后重试;\n4. 如仍报错,请联系技术支持并提供上述错误信息。"
)
输入组件
inputs = [
功能选择
gr.Dropdown(
"1. 多模态输入处理", "2. 快速预约", "3. 紧急处理", "4. 状态查询",
label="选择功能(必选)",
value="1. 多模态输入处理"
),
文本输入
gr.Textbox(label="文本输入(多模态处理用)", placeholder="例如:我想预约特斯拉Model3试驾,明天下午2点"),
音频输入
gr.Audio(type="filepath", label="音频文件(语音输入用,支持MP3/WAV)"),
图片输入
gr.Image(type="filepath", label="图片文件(驾照/车型用,支持JPG/PNG)"),
用户信息
gr.Textbox(
label="用户信息(预约/紧急处理用)",
lines=3,
placeholder="姓名:张三\n电话:13800138000\nx:100\ny:200\n偏好:scenic(可选,多偏好用逗号分隔)"
),
预约参数
gr.Dropdown("Model3", "Han", "P7", label="车型(预约用)", value="Model3"),
gr.Textbox(label="日期(预约用,格式:YYYY-MM-DD)", value=(datetime.now() + timedelta(days=1)).strftime("%Y-%m-%d")),
gr.Textbox(label="时间(预约用,格式:HH:MM)", value="14:30"), # 默认时间改为14:30,避免早于当前时间
gr.Textbox(label="地点(预约用)", value="北京市朝阳区建国路88号"),
紧急处理/查询参数
gr.Textbox(label="预约ID(紧急处理/查询用)", placeholder="例如:apt_1a2b3c4d"),
gr.Dropdown(
"vip", "press_event", "immediate_purchase",
label="紧急原因(仅紧急处理用)",
value="vip"
)
]
输出组件
outputs = gr.Textbox(
label="处理结果与对话历史(含详细规划)",
lines=25,
placeholder="处理结果将显示在这里,包含详细的预约、调度、路线、天气规划..."
)
创建基础Interface
demo = gr.Interface(
fn=handle_all_functions,
inputs=inputs,
outputs=outputs,
title="AI智能体试驾预约系统(含详细规划)",
description="""
系统特点:
-
完整规划显示:所有操作结果包含详细的预约、调度、路线、天气调整规划
-
多模态支持:文本描述、音频文件(语音)、图片文件(驾照/车型)
-
国内网络友好:天气服务、Qwen模型均支持国内网络
-
异常处理:详细错误提示和修复建议
使用步骤(快速预约示例):
-
选择功能:2. 快速预约
-
用户信息框输入:
姓名:张三
电话:13800138000
x:100
y:200
-
车型:Model3(默认)
-
日期:默认明天(无须修改)
-
时间:默认14:30(无须修改)
-
地点:默认北京市朝阳区建国路88号(无须修改)
-
点击Submit,查看预约成功结果(含详细规划)
""",
allow_flagging="never"
)
return demo
--------------------------
5. 程序入口
--------------------------
if name == "main":
try:
初始化AI智能体
agent = TestDriveAgent()
创建并启动界面
demo = create_simple_interface(agent)
启动服务
print("\n系统启动成功!请在浏览器中访问:http://localhost:7860")
demo.launch(
server_name="0.0.0.0",
server_port=7860,
share=False
)
except Exception as e:
print(f"\n系统启动失败!详细信息:")
print(f"错误类型: {type(e).name}")
print(f"错误详情: {str(e)}")
import traceback
print(f"异常栈:\n{traceback.format_exc()}")
print("\n启动失败修复建议:")
print("1. 确认Gradio版本:pip install 'gradio>=3.0,<4.0'")
print("2. 确认依赖安装:pip install requests json uuid")
print("3. 确认网络连接:Qwen模型调用需要联网(国内网络可访问DashScope)")
print("4. 检查端口占用:如7860端口被占用,修改server_port参数(如7861)")
6. 运行结果

点击运行结果中的链接,页面如图14.2所示。

图14.2 系统运行结果
