本文记录了我从零开始学习大语言模型(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更容易被模型理解。

希望我的文章能够帮助同样在路上的朋友们。

---

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐