【大模型学习之路】从零开始:我的第一个LLM应用实践
我们有一个包含5000+条车辆电路图文档的资料库,用户查找文档时使用自然语言,导致难以直接匹配。需要一个智能助手通过多轮对话引导用户找到所需资料。
本文记录了我从零开始学习大语言模型(LLM)并开发第一个实际应用项目的完整历程。希望通过分享我的学习过程、遇到的问题和解决方案,帮助同样在路上的朋友们。
为什么学习大模型?
1. 技术趋势
大语言模型正在改变软件开发的范式。从传统的规则编程到基于提示词(Prompt)的智能应用,这种转变让我看到了新的可能性。
2. 实际需求
在工作中,我遇到了一个实际问题:用户需要通过自然语言查找车辆电路图文档,但传统的关键词搜索无法很好地理解用户的真实意图。比如:
- 用户说:"我要一个东风天龙的仪表图"
- 用户说:"天龙KL的ECU图"
- 用户说:"三一挖掘机的整车电路图"
这些非标准化的表达,需要智能理解才能准确匹配到目标文档。
3. 学习目标
- ✅ 理解大语言模型的基本原理
- ✅ 掌握Prompt工程技巧
- ✅ 学会将LLM集成到实际应用中
- ✅ 解决真实业务问题
项目介绍:智能车辆电路图导航Chatbot
项目背景
我们有一个包含5000+条车辆电路图文档的资料库,用户查找文档时使用自然语言,导致难以直接匹配。需要一个智能助手通过多轮对话引导用户找到所需资料。
核心功能
1. **意图理解**:解析用户的自然语言查询,提取品牌、型号、电路图类型等信息
2. **智能检索**:基于意图在资料库中搜索相关电路图
3. **多轮对话引导**:当结果较多时,通过选择题帮助用户缩小范围
4. **结果返回**:最终返回不超过5个精准匹配的文档
示例对话
用户:我要一个东风天龙的仪表图
Chatbot:我找到了东风天龙相关的电路图。请问您需要的是:
A. 东风天龙 KL 系列
B. 东风天龙 KC 系列
C. 东风天龙 VL 系列
用户:A
Chatbot:明白了。请问您需要的是哪种类型的仪表电路图:
A. ECU 仪表针脚图
B. 整车仪表线路图
用户:整车仪表线路图
Chatbot:已为您找到以下电路图:
[ID: 12345] 东风天龙KL整车仪表电路图
---
技术选型
后端框架:FastAPI
- **原因**:Python生态,异步支持好,自动生成API文档
大语言模型:通义千问(Qwen)
- **使用场景**:
- 意图理解:将用户自然语言转换为结构化数据
- 问题生成:动态生成对话中的选择题问题
前端框架:React + Vite
数据存储:CSV文件 + 内存加载
- **原因**:数据量不大(5000+条),CSV便于维护
- **优化**:启动时加载到内存,提高查询速度
---
第一个实践:LLM服务集成
1. 环境准备
首先安装必要的依赖:
pip install dashscope # 通义千问SDK
pip install fastapi uvicorn
2. 配置API密钥
创建配置文件 `config.py`:
import os
from dotenv import load_dotenv
load_dotenv()
class Config:
ALI_QWEN_API_KEY = os.getenv("ALI_QWEN_API_KEY")
ALI_QWEN_MODEL = "qwen-turbo" # 或 qwen-plus
MAX_TOKENS = 2000
TEMPERATURE = 0.3
在 `.env` 文件中配置:
ALI_QWEN_API_KEY=your_api_key_here
3. 创建LLM服务类
import dashscope
from dashscope import Generation
class LLMService:
def __init__(self):
self.api_key = Config.ALI_QWEN_API_KEY
self.model = Config.ALI_QWEN_MODEL
dashscope.api_key = self.api_key
def call_llm(self, prompt: str, temperature: float = 0.3) -> str:
"""调用通义千问API"""
response = Generation.call(
model=self.model,
prompt=prompt,
max_tokens=2000,
temperature=temperature
)
if response.status_code == 200:
return response.output.text
else:
raise Exception(f"API调用失败: {response.message}")
4. 第一个功能:意图理解
这是项目的核心功能之一。我们需要将用户的自然语言转换为结构化数据。
**Prompt设计思路**:
1. 明确任务:告诉模型要做什么
2. 定义输出格式:要求返回JSON
3. 提供Few-Shot示例:让模型学习正确的格式
4. 明确规则:品牌识别、类型识别等
def build_intent_prompt(self, user_query: str) -> str:
prompt = f"""# 任务:车辆电路图查询意图理解
## 输入
用户查询:{user_query}
## 输出格式(必须严格遵守)
只返回JSON,格式如下:
{{
"brand": "品牌名称或null",
"model": "型号名称或null",
"diagram_type": "电路图类型或null",
"vehicle_category": "车辆类别或null",
"keywords": ["关键词1", "关键词2"],
"confidence": 0.0-1.0之间的数字
}}
规则(按优先级执行)
规则1:品牌识别(最高优先级)
1. 复合品牌必须完整返回:
- "东风天龙" → brand = "东风天龙"(不能只返回"东风")
- "一汽解放" → brand = "一汽解放"
2. 品牌简称映射:
- "天龙" → brand = "东风天龙"
- "JH6" → brand = "解放JH6"
规则2:电路图类型识别
1. "仪表图"、"仪表" → diagram_type = "仪表电路图"
2. "ECU图"、"ECU" → diagram_type = "ECU电路图"
3. "整车图" → diagram_type = "整车电路图"
示例(Few-Shot Learning)
示例1:
输入:我要一个东风天龙的仪表图
输出:{{"brand": "东风天龙", "model": null, "diagram_type": "仪表电路图", "vehicle_category": null, "keywords": [], "confidence": 0.9}}
示例2:
输入:天龙KL的ECU图
输出:{{"brand": "东风天龙", "model": "天龙KL", "diagram_type": "ECU电路图", "vehicle_category": null, "keywords": [], "confidence": 0.85}}
## 开始解析
严格按照上述规则和示例格式,只返回JSON,不要有任何其他文字。
**调用示例**:
def parse_intent(self, user_query: str) -> IntentResult:
prompt = self.build_intent_prompt(user_query)
response_text = self.call_llm(prompt, temperature=0.1) # 低温度提高一致性
intent_dict = json.loads(response_text)
return IntentResult(**intent_dict)
---
遇到的挑战与解决方案
挑战1:LLM输出不一致
**问题**:同样的输入,LLM有时返回不同的格式,导致JSON解析失败。
**解决方案**:
1. **降低Temperature**:从0.3降到0.1,提高输出一致性
2. **明确输出格式**:在Prompt中强调"只返回JSON,不要有任何其他文字"
3. **添加JSON提取逻辑**:即使有额外文字,也能提取出JSON部分
def parse_intent(self, user_query: str) -> IntentResult:
prompt = self.build_intent_prompt(user_query)
response_text = self.call_llm(prompt, temperature=0.1) # 低温度提高一致性
intent_dict = json.loads(response_text)
return IntentResult(**intent_dict)
挑战2:品牌识别不准确
**问题**:用户说"天龙",LLM有时只返回"天龙"而不是"东风天龙"。
**解决方案**:
1. **代码层面强制修正**:即使LLM输出不一致,代码也会强制补全
2. **品牌映射表**:维护一个品牌简称到完整名称的映射
def _validate_and_enforce_rules(self, result: IntentResult, user_query: str) -> IntentResult:
"""验证并强制执行关键业务规则"""
# 规则1:如果查询包含"东风天龙",强制设置为"东风天龙"
if "东风天龙" in user_query:
if result.brand != "东风天龙":
result.brand = "东风天龙"
挑战3:Prompt工程优化
**问题**:如何设计一个好的Prompt,让LLM准确理解任务?
**经验总结**:
1. **结构化Prompt**:使用Markdown格式,层次清晰
2. **Few-Shot Learning**:提供3-5个示例,让模型学习
3. **明确规则优先级**:使用"必须"、"禁止"等明确词汇
4. **输出格式约束**:明确要求输出格式,减少解析错误
---
项目成果
经过几天的开发,项目已经实现了:
- 意图理解功能:准确率约90%
- 智能检索功能:支持层级路径和关键词匹配
- 多轮对话引导:动态生成选择题
- Web界面:React前端 + FastAPI后端
- Docker部署:支持一键部署到生产环境
项目地址:[https://github.com/landc3/Navigation_Chatbot.git]
---
学习心得
好的Prompt能让模型准确理解任务,Few-Shot示例比长篇说明更有效,结构化、层次化的Prompt更容易被模型理解。
希望我的文章能够帮助同样在路上的朋友们。
---
更多推荐


所有评论(0)