AI——DeepSeek+LangChain+streamlit 实现智能汽车维修服务

效果图

分析流程

代码实现

废话少说,直接上代码

from langchain_core.language_models.llms import BaseLLM
from langchain_core.outputs import Generation, LLMResult
from pydantic.v1 import Field, validator
from typing import Any, Dict, List, Optional, AsyncIterator
import requests
import osclass DeepSeekLLM(BaseLLM):api_key: str = Field(alias="api_key")model: str = "deepseek-chat"temperature: float = 0.7max_tokens: int = 1000# 必须实现的抽象方法def _generate(self,prompts: List[str],stop: Optional[List[str]] = None,**kwargs: Any,) -> LLMResult:print("_generate:")generations = []for prompt in prompts:response = self._call_api(prompt)generations.append([Generation(text=response)])return LLMResult(generations=generations)async def _agenerate(self,prompts: List[str],stop: Optional[List[str]] = None,**kwargs: Any,) -> LLMResult:# 异步实现(可选)return self._generate(prompts, stop, **kwargs)def _call_api(self, prompt: str) -> str:try:headers = {"Authorization": f"Bearer {self.api_key}","Content-Type": "application/json"}payload = {"messages": [{"role": "user", "content": prompt}],"model": self.model,"temperature": self.temperature,"max_tokens": self.max_tokens}#将输入 输出都保存到文件中 import json# 添加一个分隔符 没有  json.txt 就创建with open("json.txt", "a", encoding="utf-8") as f:json.dump(payload, f, ensure_ascii=False, indent=4)response = requests.post("https://api.deepseek.com/v1/chat/completions",headers=headers,json=payload,timeout=30)with open("json.txt", "a", encoding="utf-8") as f:json.dump(response.json(), f, ensure_ascii=False, indent=4)# 增加响应内容验证if not response.text.strip():raise ValueError("API返回空响应")try:data = response.json()except json.JSONDecodeError:# 尝试提取可能的JSON片段import rejson_match = re.search(r'```json\n({.*?})\n```', response.text, re.DOTALL)if json_match:data = json.loads(json_match.group(1))else:raise ValueError(f"无法解析API响应: {response.text[:200]}...")# 验证关键字段if not data.get("choices") or not isinstance(data["choices"], list):raise ValueError("API返回格式异常,缺少choices字段")content = data["choices"][0]["message"]["content"]# 清理响应内容(去除可能的Markdown标记)if content.startswith("```json"):content = content[7:-3].strip()return contentexcept requests.exceptions.RequestException as e:raise ValueError(f"API请求失败: {str(e)}")except Exception as e:raise ValueError(f"处理API响应时出错: {str(e)}")@propertydef _llm_type(self) -> str:return "deepseek"
car_diagnosis_app.py 代码 
import streamlit as st
from langchain.chains import SequentialChain, TransformChain
from langchain.memory import ConversationBufferMemory
from langchain.prompts import PromptTemplate
from langchain.chains.llm import LLMChain
from deepseek_llm import DeepSeekLLM
import json
import datetime
import random
import os# 初始化DeepSeek LLM
api_key = os.getenv("DEEPSEEK_API_KEY", st.secrets.get("DEEPSEEK_API_KEY", "your-api-key"))
llm = DeepSeekLLM(api_key=api_key, temperature=0.3, max_tokens=1500)# 模拟车辆数据库
VEHICLE_DB = {"京A12345": {"brand": "Toyota","model": "Camry","year": 2020,"mileage": 45000,"last_service": "2023-12-15","insurance_expiry": "2024-09-30","next_maintenance": "2024-06-30"},"沪B67890": {"brand": "Honda","model": "CR-V","year": 2019,"mileage": 60000,"last_service": "2023-11-20","insurance_expiry": "2024-08-15","next_maintenance": "2024-05-20"}
}# 模拟维修店数据库
REPAIR_SHOPS = [{"id": 1, "name": "诚信汽修", "distance": "1.2km", "rating": 4.8, "services": ["机油更换", "刹车维修", "发动机诊断"], "price_level": "$$"},{"id": 2, "name": "途虎养车工场店", "distance": "2.3km", "rating": 4.7, "services": ["轮胎更换", "保养套餐", "电子诊断"], "price_level": "$$$"},{"id": 3, "name": "小李快修", "distance": "0.8km", "rating": 4.5, "services": ["快速保养", "玻璃水加注", "简单维修"], "price_level": "$"}
]# 模拟知识库音频
SOUND_LIBRARY = {"哒哒声": "https://example.com/sounds/ticking.mp3","嗡嗡声": "https://example.com/sounds/humming.mp3","吱吱声": "https://example.com/sounds/squeaking.mp3","咔嗒声": "https://example.com/sounds/clicking.mp3"
}# 1. 信息提取链
def extract_vehicle_info(inputs: dict) -> dict:license_plate = inputs["license_plate"]vehicle_info = VEHICLE_DB.get(license_plate, {})if not vehicle_info:st.error(f"未找到车牌号 {license_plate} 的车辆信息")return {"vehicle_info": "未知车辆"}# 检查服务提醒today = datetime.date.today()reminders = []insurance_expiry = datetime.datetime.strptime(vehicle_info["insurance_expiry"], "%Y-%m-%d").date()if (insurance_expiry - today).days < 30:reminders.append({"type": "insurance", "message": "您的车辆保险即将到期"})next_maintenance = datetime.datetime.strptime(vehicle_info["next_maintenance"], "%Y-%m-%d").date()if (next_maintenance - today).days < 30:reminders.append({"type": "maintenance", "message": "您的车辆即将需要保养"})return {"vehicle_info": json.dumps(vehicle_info),"reminders": json.dumps(reminders)}info_extraction_chain = TransformChain(input_variables=["license_plate"],output_variables=["vehicle_info", "reminders"],transform=extract_vehicle_info
)# 2. 诊断链
def setup_diagnosis_chain():diagnosis_template = """您是一名专业的汽车维修技师,正在帮助车主诊断车辆问题。请根据以下信息进行诊断:车辆信息:{vehicle_info}用户描述的症状:{symptoms}请根据您的专业知识:1. 分析可能的故障原因2. 生成最多3个关键问题来进一步明确问题3. 对于异响类问题,请建议用户试听哪种声音样本输出格式:{{"analysis": "对问题的初步分析","questions": ["问题1", "问题2", "问题3"],"sound_suggestion": "建议试听的声音类型"}}"""prompt = PromptTemplate(template=diagnosis_template,input_variables=["vehicle_info", "symptoms"])return LLMChain(llm=llm, prompt=prompt, output_key="diagnosis_result")# 3. 维修决策链
def setup_repair_decision_chain():decision_template = """基于以下诊断信息:{diagnosis_result}请判断:1. 车主是否能够自行修复问题?(是/否)2. 如果可自行修复,提供详细的步骤指导3. 如果需要专业维修,推荐维修项目输出格式:{{"self_repairable": true/false,"repair_steps": ["步骤1", "步骤2", ...],"recommended_services": ["服务1", "服务2", ...]}}"""prompt = PromptTemplate(template=decision_template,input_variables=["diagnosis_result"])return LLMChain(llm=llm, prompt=prompt, output_key="repair_decision")# 4. 门店推荐链
def recommend_shops(inputs: dict) -> dict:decision = json.loads(inputs["repair_decision"])if decision.get("self_repairable", False):return {"shop_recommendations": json.dumps([])}# 根据位置和推荐服务筛选门店location = inputs["location"]recommended_services = decision.get("recommended_services", [])filtered_shops = []for shop in REPAIR_SHOPS:# 简单匹配服务(实际应用中应有更复杂的匹配逻辑)if any(service in shop["services"] for service in recommended_services):shop["match_score"] = random.uniform(0.7, 1.0)  # 模拟匹配度计算filtered_shops.append(shop)# 按距离和评分排序filtered_shops.sort(key=lambda x: (x["distance"], -x["rating"]))return {"shop_recommendations": json.dumps(filtered_shops[:3])}shop_recommendation_chain = TransformChain(input_variables=["repair_decision", "location"],output_variables=["shop_recommendations"],transform=recommend_shops
)# 完整工作流
def create_full_workflow():diagnosis_chain = setup_diagnosis_chain()repair_decision_chain = setup_repair_decision_chain()return SequentialChain(chains=[info_extraction_chain,diagnosis_chain,repair_decision_chain,shop_recommendation_chain],input_variables=["license_plate", "symptoms", "location"],output_variables=["vehicle_info", "reminders", "diagnosis_result", "repair_decision", "shop_recommendations"],verbose=True)# Streamlit UI
def main():st.set_page_config(page_title="智能汽车故障诊断", layout="wide")st.title("🚗 智能汽车故障诊断助手")# 初始化session状态if "diagnosis_stage" not in st.session_state:st.session_state.diagnosis_stage = "initial"st.session_state.memory = ConversationBufferMemory()st.session_state.workflow = create_full_workflow()st.session_state.answers = {}st.session_state.current_questions = []# 侧边栏 - 车辆信息输入with st.sidebar:st.header("车辆信息")license_plate = st.text_input("车牌号", "京A12345")location = st.text_input("当前位置", "北京市海淀区")st.header("车辆状态")if license_plate in VEHICLE_DB:vehicle = VEHICLE_DB[license_plate]st.write(f"品牌: {vehicle['brand']}")st.write(f"型号: {vehicle['model']}")st.write(f"里程: {vehicle['mileage']}公里")st.write(f"上次保养: {vehicle['last_service']}")# 服务提醒today = datetime.date.today()insurance_expiry = datetime.datetime.strptime(vehicle["insurance_expiry"], "%Y-%m-%d").date()if (insurance_expiry - today).days < 30:st.warning(f"⏰ 保险将于 {vehicle['insurance_expiry']} 到期")next_maintenance = datetime.datetime.strptime(vehicle["next_maintenance"], "%Y-%m-%d").date()if (next_maintenance - today).days < 30:st.warning(f"🔧 下次保养时间: {vehicle['next_maintenance']}")# 主界面 - 诊断流程if st.session_state.diagnosis_stage == "initial":st.subheader("请描述您的车辆问题")symptoms = st.text_area("例如:冷启动时有哒哒异响,仪表盘机油灯闪烁", height=150)if st.button("开始诊断"):if not symptoms.strip():st.error("请输入车辆问题描述")returnst.session_state.symptoms = symptomsst.session_state.license_plate = license_platest.session_state.location = locationst.session_state.diagnosis_stage = "processing"st.rerun()# 诊断处理中elif st.session_state.diagnosis_stage == "processing":with st.spinner("正在分析您的车辆问题..."):try:# 执行工作流result = st.session_state.workflow({"license_plate": st.session_state.license_plate,"symptoms": st.session_state.symptoms,"location": st.session_state.location})# 解析结果diagnosis_result = json.loads(result["diagnosis_result"])repair_decision = json.loads(result["repair_decision"])shop_recommendations = json.loads(result["shop_recommendations"])# 存储结果st.session_state.diagnosis_result = diagnosis_resultst.session_state.repair_decision = repair_decisionst.session_state.shop_recommendations = shop_recommendationsst.session_state.current_questions = diagnosis_result.get("questions", [])# 如果有声音建议,准备音频sound_type = diagnosis_result.get("sound_suggestion")if sound_type and sound_type in SOUND_LIBRARY:st.session_state.sound_url = SOUND_LIBRARY[sound_type]else:st.session_state.sound_url = Nonest.session_state.diagnosis_stage = "show_results"st.rerun()except Exception as e:st.error(f"诊断过程中发生错误: {str(e)}")st.session_state.diagnosis_stage = "initial"# 显示诊断结果elif st.session_state.diagnosis_stage == "show_results":st.subheader("诊断结果")# 显示初步分析st.markdown(f"**问题分析:** {st.session_state.diagnosis_result.get('analysis', '')}")# 播放声音建议if st.session_state.sound_url:st.markdown("**声音对比:** 请听以下声音是否与您的车辆声音相似")st.audio(st.session_state.sound_url, format='audio/mp3')# 显示进一步问题if st.session_state.current_questions:st.markdown("**请回答以下问题以进一步明确问题:**")for i, question in enumerate(st.session_state.current_questions):st.session_state.answers[i] = st.text_input(question, key=f"q_{i}")if st.button("提交答案并继续诊断"):# 将答案添加到症状描述中new_symptoms = "\n".join([f"Q: {st.session_state.current_questions[i]}\nA: {st.session_state.answers[i]}" for i in range(len(st.session_state.current_questions))])st.session_state.symptoms += "\n" + new_symptomsst.session_state.diagnosis_stage = "processing"st.rerun()# 显示维修决策st.divider()decision = st.session_state.repair_decisionif decision.get("self_repairable", False):st.success("✅ 您可以尝试自行修复此问题")st.markdown("**修复步骤:**")for i, step in enumerate(decision.get("repair_steps", [])):st.markdown(f"{i+1}. {step}")# 添加AR指导按钮if st.button("查看AR修复指导"):st.session_state.show_ar = Trueif st.session_state.get("show_ar", False):st.video("https://example.com/ar_repair_guide.mp4")else:st.warning("⚠️ 建议到专业维修店处理此问题")st.markdown(f"**推荐维修项目:** {', '.join(decision.get('recommended_services', []))}")# 显示推荐门店st.subheader("推荐维修店")if st.session_state.shop_recommendations:cols = st.columns(len(st.session_state.shop_recommendations))for i, shop in enumerate(st.session_state.shop_recommendations):with cols[i]:st.markdown(f"**{shop['name']}**")st.caption(f"距离: {shop['distance']} | 评分: {shop['rating']}")st.caption(f"服务: {', '.join(shop['services'][:3])}")st.caption(f"价格: {shop['price_level']}")if st.button("选择此门店", key=f"shop_{i}"):st.session_state.selected_shop = shopst.session_state.diagnosis_stage = "shop_selected"st.rerun()else:st.info("未找到匹配的维修店,请尝试扩大搜索范围")# 返回按钮if st.button("重新诊断"):st.session_state.diagnosis_stage = "initial"st.rerun()# 门店选择后elif st.session_state.diagnosis_stage == "shop_selected":shop = st.session_state.selected_shopst.success(f"您已选择: {shop['name']}")# 显示预约信息st.subheader("预约信息")date = st.date_input("预约日期", min_value=datetime.date.today())time = st.time_input("预约时间", datetime.time(10, 00))contact = st.text_input("联系电话")# 维修项目确认st.subheader("维修项目确认")services = st.session_state.repair_decision.get("recommended_services", [])selected_services = st.multiselect("请确认维修项目", services, default=services)if st.button("确认预约"):st.session_state.appointment = {"shop": shop["name"],"date": date.strftime("%Y-%m-%d"),"time": time.strftime("%H:%M"),"services": selected_services,"contact": contact}st.session_state.diagnosis_stage = "appointment_confirmed"st.rerun()# 预约确认elif st.session_state.diagnosis_stage == "appointment_confirmed":appt = st.session_state.appointmentst.balloons()st.success("🎉 预约成功!")st.markdown(f"""**维修店:** {appt['shop']}  **时间:** {appt['date']} {appt['time']}  **维修项目:** {', '.join(appt['services'])}  **联系电话:** {appt['contact']}""")st.info("维修店将很快联系您确认预约详情")if st.button("返回主页"):st.session_state.diagnosis_stage = "initial"st.rerun()if __name__ == "__main__":main()

执行脚本

#环境比变量
export DEEPSEEK_API_KEY=your_api_key
#安装依赖
pip install streamlit langchain requests
#运行应用
streamlit run car_diagnosis_app.py
#访问应用
http://localhost:8501

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/bicheng/84720.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《C++ 继承》

目录 继承的定义 继承类模板 派生类和基类之前的转换 隐藏 派生类的默认成员函数 不能被继承的类 继承中的友元和静态成员 继承模型 继承的定义 继承的本质是一种复用。规定Person类为基类&#xff0c;Student类为派生类 。 继承方式分为public继承&#xff0c;prote…

金蝶K3 ERP 跨网段访问服务器卡顿问题排查和解决方法

我一朋友公司反应&#xff0c;公司网络卡顿&#xff0c;测试掉包严重&#xff0c;抓包wireshark测试&#xff0c;发现arp包有大量mac欺骗&#xff0c;因为公司有几百台电脑&#xff0c;所以建议更换了三层交换机&#xff0c;划分了vlan&#xff0c;这样有效的避免了网络风暴等&…

无需安装!在线数据库工具 :实战 SQL 语句经典案例

在数字化时代&#xff0c;SQL&#xff08;结构化查询语言&#xff09;已成为数据从业者、开发人员乃至业务分析人员必备的核心技能。无论是处理日常数据报表&#xff0c;还是应对复杂的业务逻辑&#xff0c;SQL 都能高效实现数据的查询、操作与分析。本文将通过经典的 SQL 练习…

如何在网页里填写 PDF下拉框

对于PDF 开发者或网页开发者来说&#xff0c;让用户在网站上填写 PDF 下拉框&#xff08;Combo Box&#xff09;是一个棘手的问题。因为 PDF 并不是一种原生的 Web 格式&#xff0c;浏览器通常不允许用户与 PDF 下拉框进行交互。 那么&#xff0c;如何让用户在 HTML 中填写 PD…

.Net 优秀框架 ABP全面详解

文章目录 第一部分&#xff1a;ABP框架概述与核心架构1.1 ABP框架简介1.2 ABP框架架构解析1.2.1 表现层(Presentation Layer)1.2.2 分布式服务层(Distributed Service Layer)1.2.3 应用层(Application Layer)1.2.4 领域层(Domain Layer)1.2.5 基础设施层(Infrastructure Layer)…

力扣-198.打家劫舍

题目描述 你是一个专业的小偷&#xff0c;计划偷窃沿街的房屋。每间房内都藏有一定的现金&#xff0c;影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统&#xff0c;如果两间相邻的房屋在同一晚上被小偷闯入&#xff0c;系统会自动报警。 给定一个代表每个房屋…

windows 安装vllm cuda版本

windows 安装cuda版本 查看window cuda版本 nvidia-smi vllm 获取镜像,此版本需要cuda 版本12.8 或以上 docker pull vllm/vllm-openai:latest下载模型 git lfs installcd e:\ai mkdir vllm\models\qwen2cd vllm\models#通过git下载git clone https://www.modelscope.c…

Node.js特训专栏-基础篇:1. Node.js环境搭建与项目初始化详细指南

我将为你详细讲解 Node.js 环境搭建与项目初始化的步骤&#xff0c;包含常见问题解决和最佳实践&#xff0c;帮助你快速上手。 详细步骤说明 1. 环境搭建 Windows用户&#xff1a; 访问Node.js官网(https://nodejs.org)下载LTS版本安装包&#xff08;推荐长期支持版&#xf…

13.安卓逆向2-frida hook技术-HookJava构造方法

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;图灵Python学院 工具下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1bb8NhJc9eTuLzQr39lF55Q?pwdzy89 提取码&#xff1…

php基础:常见函数

内建函数 文章目录 内建函数1、文件操作函数&#xff1a;2、代码执行函数&#xff1a;3、反序列化函数&#xff1a;4、数据库操作函数&#xff1a;5、类型转换与比较函数&#xff1a;6、其他常见函数&#xff1a; 1、文件操作函数&#xff1a; include(): 导入并执行指定的 PHP…

教程:PyCharm 中搭建多级隔离的 Poetry 环境(从 Anaconda 到项目专属.venv)

核心思维&#xff1a;为什么需要 “多级隔离”&#xff1f; 在复杂项目中&#xff0c;环境冲突是最棘手的问题&#xff08;比如系统 Python 版本不同、依赖包版本冲突&#xff09;。通过 “Anaconda 虚拟环境 → 项目 Poetry 环境 → 工具级隔离” 的三层架构&#xff0c;实现…

Rollup vs Webpack 深度对比:前端构建工具终极指南

前端工程领域始终面临一个根本选择&#xff1a;如何在模块化编码规范与工程化构建效率之间取得最佳平衡。Rollup与Webpack分别代表着两种不同维度的解决方案&#xff0c;本文将揭示它们的真实应用场景与核心差异。 一、核心差异全景图&#xff08;附最新对比&#xff09; 核心能…

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…

Easy Excel

Easy Excel 一、依赖引入二、基本使用1. 定义实体类&#xff08;导入/导出共用&#xff09;2. 写 Excel3. 读 Excel 三、常用注解说明&#xff08;完整列表&#xff09;四、进阶&#xff1a;自定义转换器&#xff08;Converter&#xff09; 其它自定义转换器没生效 Easy Excel在…

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…

AI高考志愿助手应用架构设计并上线实施运行

环境: AI高考志愿助手 问题描述: AI高考志愿助手应用架构设计并上线实施运行 业务需求:开发一个AI升学助手,功能是帮助用户模拟填报高考志愿等功能,数据是历年各专业的录取分数线表格。数据确认: 近3年约100多万条数据,原始数据是excel表格数据。解决方案: 一、项…

深入浅出掌握 Axios(持续更新)

在了解ajax和axios之前&#xff0c;我们先观察一下他们是什么英文的缩写 ajax 的名字为 asynchroanous JavaScript and XML 而axios的名称来源于英文单词“axis”与“I/O”的结合&#xff0c;并非直接缩写自某个特定短语。 先导知识 在本文我们简单的介绍一下ajax后着重讲解…

windows10下搭建nfs服务器

windows10下搭建nfs服务器 有参考这篇博客 Windows10搭建NFS服务 - fuzidage - 博客园 下载 NFS Server这个app 通过网盘分享的文件&#xff1a;nfs1268 (1).exe 链接: https://pan.baidu.com/s/1rE4h710Uh-13kWGXvjkZzw 提取码: mwa4 --来自百度网盘超级会员v5的分享 下载后…

npm符号链接

前言 最近在写一个快应用项目&#xff0c;demo中依赖了本地文件&#xff0c;package.json如下&#xff1a; 此时 node_modules 下出现了 mysdk&#xff0c;复制整个项目&#xff0c;但是copy的项目中的node_modules并未出现该文件&#xff0c;导致报错。 解决方案 观察 pa…

SQL 中 IDENTITY 列的特殊处理.

SQL 处理中,遇到提示: "消息 544,级别 16,状态 1,第 3 行 当 IDENTITY_INSERT 设置为 OFF 时,不能为表 BM 中的标识列插入显式值。" 即当 SQL Server 表中的 ​​标识列(Identity Column)​​ 插入显式值,但未启用 IDENTITY_INSERT 选项。由此报错,以下是详…