🧊 冻冻智能数据分析助手基于 LangChain + LM Studio 的 语义层 NL2SQL 数据分析系统，支持用自然语言查询业务数据，自动生成 SQL、可视化图表和分析结论。git地址https://github.com/zxliucn/Datas_Agent目录项目概述技术架构项目结构核心模块4.1 主入口 (app.py)4.2 意图解析 (core/intent_parser.py)4.3 SQL 构建 (core/sql_builder.py)4.4 SQL 执行 (core/sql_executor.py)4.5 图表生成 (core/chart_generator.py)4.6 洞察生成 (core/insight_generator.py)查询模板系统 (templates)Web 界面 (web)工具模块 (utils)配置说明数据库表结构快速开始API 接口项目预览1. 项目概述冻冻智能数据分析助手是一个基于语义层 NL2SQL 架构的数据分析系统，采用 预定义模板 + LLM 意图解析 的安全方案，避免 LLM 直接生成 SQL 带来的安全风险。核心特性功能说明🔍 自然语言查询输入自然语言问题，自动解析意图并生成 SQL📊 可视化图表根据查询类型自动选择折线图、柱状图、饼图等💡 智能洞察从查询结果中提取关键结论和业务建议🔒 安全可控预定义 SQL 模板，LLM 仅负责意图解析，不直接生成 SQL🌐 Web 界面基于 Gradio 的可视化交互界面支持的查询类型查询类型示例问题商品销量虾滑卖了多少？上个月牛筋的销售额商品排行这个月哪个商品卖得最好？销量前10订单趋势最近7天的订单趋势订单列表待发货的订单有哪些？客户排行哪个客户花钱最多？库存预警库存不足的商品售后排行退款最多的商品经营概况本月经营情况2. 技术架构┌─────────────────────────────────────────────────────────┐ │ Gradio Web UI │ │ 输入自然语言问题 → 展示图表和洞察结论 │ └──────────────────────┬──────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────┐ │ NL2SQL 主控制器 │ │ 意图解析 → SQL 构建 → 执行 → 可视化 │ └──────────────────────┬──────────────────────────────────┘ │ ┌──────────────┼──────────────┐ ▼ ▼ ▼ ┌──────────────┐ ┌────────────┐ ┌──────────────┐ │ IntentParser │ │ SQLBuilder │ │ SQLExecutor │ │ LLM 意图解析 │ │ 模板拼装 │ │ MySQL 查询 │ └──────────────┘ └────────────┘ └──────────────┘ │ ┌──────────────┼──────────────┐ ▼ ▼ ▼ ┌──────────────┐ ┌────────────┐ ┌──────────────┐ │ChartGenerator│ │ InsightGen │ │ QueryTemplates│ │ 图表可视化 │ │ 洞察分析 │ │ SQL 模板库 │ └──────────────┘ └────────────┘ └──────────────┘设计思路采用 语义层 NL2SQL 方案，而非让 LLM 直接生成 SQL：LLM 只做意图解析：理解用户自然语言，输出结构化的 {intent, params} JSONSQL 由模板拼装：每种查询类型对应预定义的 SQL 模板，安全可控参数映射处理：通过 param_mapping 将自然语言参数（如"上个月"）转换为 SQL 条件优势：✅ 安全：杜绝 SQL 注入风险✅ 可控：SQL 逻辑可审查、可维护✅ 稳定：不依赖 LLM 生成正确 SQL 的能力✅ 可扩展：新增查询类型只需添加模板3. 项目结构Datas_agent/ ├── app.py # 主入口，启动服务 ├── config.py # 配置文件（数据库、LLM） ├── .env # 环境变量 ├── requirements.txt # 依赖清单 │ ├── core/ # 核心业务模块 │ ├── __init__.py │ ├── intent_parser.py # LLM 意图解析 │ ├── sql_builder.py # SQL 模板拼装 │ ├── sql_executor.py # SQL 执行器 │ ├── chart_generator.py # 图表生成（Plotly） │ └── insight_generator.py # 洞察分析生成 │ ├── templates/ # SQL 查询模板 │ ├── __init__.py │ └── query_templates.py # 8 种查询模板定义 │ ├── web/ # Web 界面 │ ├── __init__.py │ └── gradio_app.py # Gradio 界面 │ ├── utils/ # 工具模块 │ ├── __init__.py │ └── logger.py # 日志与计时 │ └── preview/ # 预览截图 ├── p1.png └── p2.png4. 核心模块4.1 主入口 (app.py)NL2SQL 主控制器，串联整个处理流程：class NL2SQL: def __init__(self, llm): self.intent_parser = IntentParser(llm) # LLM 意图解析 self.sql_builder = SQLBuilder() # SQL 模板拼装 def convert(self, question): # 1. 解析意图 → {intent, params} result = self.intent_parser.parse_with_defaults(question) # 2. 构建 SQL sql = self.sql_builder.build(intent, params) return intent, sql, params启动流程：初始化 LLM → 创建各模块 → 测试数据库连接 → 启动 Gradio Web 界面（端口 7861）4.2 意图解析 (core/intent_parser.py)使用 LLM 将自然语言问题解析为结构化的意图和参数。处理流程：将用户问题 + 预定义的意图列表作为 Prompt 发送给 LLMLLM 返回 JSON 格式的 {intent, params}提取 JSON 并解析，失败则返回 unknown调用 parse_with_defaults() 自动填充默认参数Prompt 策略：提供 8 种查询类型的触发词、参数说明和示例强制 JSON 输出格式使用 %s 占位符避免 format 冲突输出示例：// 输入："上个月虾滑卖了多少" {"intent": "product_sales", "params": {"product": "虾滑", "time_range": "last_month"}} // 输入："销量前10的商品" {"intent": "product_ranking", "params": {"top_n": 10}}4.3 SQL 构建 (core/sql_builder.py)根据意图和参数，从预定义模板拼装 SQL。构建流程：从模板库获取 SQL 模板应用默认值（如 limit=10, time_range=this_month）通过 param_mapping 映射参数（如将 time_range 转换为 AND DATE(o.order_time) = ...）填充模板占位符清理 SQL（修复空 WHERE、多余 AND 等边界情况）4.4 SQL 执行 (core/sql_executor.py)基于 SQLAlchemy + PyMySQL 执行 SQL 查询。仅允许 SELECT 查询，拒绝写操作返回 pandas DataFrame启动时自动测试数据库连接4.5 图表生成 (core/chart_generator.py)基于 Plotly 根据查询意图自动选择图表类型：意图类型图表类型说明order_trend折线图时间趋势，支持多指标product_ranking柱状图排行榜，限显前 15 条customer_ranking柱状图（绿色）客户消费排行stock_warning柱状图（红色）库存预警after_sale_ranking柱状图（橙色）售后排行product_salesMarkdown 指标卡单商品销量详情business_overviewMarkdown 表格经营概况其他自动判断饼图/柱状图/折线图4.6 洞察生成 (core/insight_generator.py)从查询结果中提取关键结论和业务建议，输出 Markdown 格式。分析维度：商品排行：Top3、总销量、集中度分析（Top3 占比）订单趋势：日均数据、升降趋势判断、峰值日期客户排行：VIP 客户识别、人均消费库存预警：最紧急商品、按分类统计、补货建议售后排行：退款率分析、改进建议经营概况：核心指标表格、退款率评级5. 查询模板系统 (templates)query_templates.py 定义了 8 种查询模板，每种模板包含：字段说明templateSQL 模板字符串，{placeholder} 占位required_params必填参数列表optional_params可选参数列表param_mapping参数到 SQL 条件的映射函数defaults默认值字典时间范围转换：支持 today、yesterday、this_week、this_month、last_month、last_7_days、last_30_days，自动转换为 MySQL 日期函数。参数映射函数示例：# 时间范围 → WHERE 条件 "time_range": lambda x: f"AND {get_time_condition(x)}" # 商品分类 → 分类过滤 "category": lambda x: f"AND p.category = '{x}'" # 经营概况 → 同时返回时间条件和中文时间名（tuple） "time_range": lambda x: (get_time_condition(x), get_time_range_name(x))6. Web 界面 (web)基于 Gradio 的交互式 Web 界面。界面布局：输入区：文本框 + 开始分析 / 清空按钮SQL 展示：代码块展示生成的 SQL图表区：Plotly 交互式图表洞察区：Markdown 格式的分析结论内置示例问题：提供各查询类型的示例问题，引导用户使用。7. 工具模块 (utils)日志模块 (logger.py)info / debug / error / warn 四级日志@timing 装饰器：记录函数执行耗时通过 APP_CONFIG['debug'] 控制是否输出 DEBUG 级别日志8. 配置说明环境变量 (.env)# MySQL 数据库 MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_USER=your_username MYSQL_PASSWORD=your_password MYSQL_DATABASE=your_database # LM Studio 本地模型 # base_url: LM Studio API 地址 # model: 使用的模型（如 qwen/qwen3.5-9b） # temperature: 0（意图解析需要确定性输出）应用配置 (config.py)LM_STUDIO_CONFIG = { 'base_url': 'http://127.0.0.1:1234/v1', 'model': 'qwen/qwen3.5-9b', 'temperature': 0, 'max_tokens': 512, } APP_CONFIG = { 'default_limit': 100, 'max_limit': 1000, 'debug': True, }9. 数据库表结构系统依赖以下 MySQL 表：表名说明关键字段products商品表product_id, name, category, price, stockorders订单表order_id, user_id, order_time, total_amount, order_statusorder_items订单明细表order_id, product_id, product_name, quantity, total_priceusers用户表id, username, nicknameafter_sale_item售后表order_id, product_name, refund_num, refund_amount10. 快速开始安装依赖pip install -r requirements.txt主要依赖：langchain-openai — LLM 调用（兼容 OpenAI API 格式）gradio — Web 界面plotly — 图表可视化pandas — 数据处理sqlalchemy + pymysql — 数据库连接python-dotenv — 环境变量管理配置启动 LM Studio 并加载模型（如 Qwen3.5-9B），确保 API 服务运行在 http://127.0.0.1:1234/v1修改 .env 文件中的 MySQL 连接信息启动服务python app.py启动成功后访问：http://localhost:7861试试这些问题虾滑卖了多少？ 这个月哪个商品卖得最好？ 最近7天的订单趋势 待发货的订单有哪些？ 哪个客户花钱最多？ 库存不足的商品 退款最多的商品 本月经营情况11. API 接口系统通过 Gradio 提供交互式 Web 接口（端口 7861），无需额外 API 调用。直接在浏览器中访问即可使用。如需集成到其他系统，可参考 NL2SQL.convert() 方法封装为 REST API：from app import NL2SQL from core import SQLExecutor nl2sql = NL2SQL(llm) executor = SQLExecutor() intent, sql, params = nl2sql.convert("虾滑卖了多少") df = executor.execute(sql)12. 项目预览系统提供基于 Gradio 的 Web 数据分析界面，输入自然语言即可获得 SQL、图表和洞察结论。界面预览![数据分析界面-主视图]图 1：智能数据分析助手主界面 — 自然语言输入与结果展示![数据分析界面-功能展示]图 2：查询结果展示 — SQL 语句、可视化图表与分析结论总结特性实现方式🔒 安全可控语义层模板方案，LLM 仅解析意图，不直接生成 SQL🧠 智能解析LangChain + LM Studio 本地大模型📊 自动可视化Plotly 按意图自动匹配图表类型💡 业务洞察基于查询结果生成结构化分析结论🚀 快速扩展新增查询类型只需添加模板，无需修改 LLM 逻辑
冻冻网络智能客服系统基于 LangGraph + Ollama 的企业级智能客服系统，支持商品查询、订单查询、售后进度查询、烹饪指南等功能。git地址https://github.com/zxliucn/Customer_Services目录项目概述技术架构项目结构核心模块4.1 入口文件4.2 Agent 图结构4.3 状态管理4.4 LLM 配置工具模块 (tools)5.1 商品工具5.2 订单工具5.3 售后工具5.4 信息提取器5.5 用户与会话Agent 节点 (agent/node)6.1 意图识别6.2 路由6.3 工具调用6.4 RAG 检索6.5 回答生成6.6 直接回答6.7 帮助信息6.8 转人工RAG 系统配置说明数据库表结构快速开始项目预览API 接口1. 项目概述冻冻网络智能客服是一个基于 LangGraph 构建的企业级对话系统，采用多节点协作架构，支持：功能说明📦 商品查询价格、规格、库存🚚 订单查询订单状态、物流进度💰 售后进度退款/退货/换货进度🍳 烹饪指南食材做法食谱👨‍💼 转人工投诉等复杂问题转人工核心特性：🎯 意图识别 + 规则匹配混合决策🔧 工具调用：订单/商品/售后数据库查询📚 RAG 检索：用户手册 + 烹饪指南💾 多轮对话记忆 (MemorySaver)🏷️ 游客/登录用户区分2. 技术架构┌─────────────────────────────────────────────────────────────┐ │ FastAPI 入口 │ │ /chat, /health │ └─────────────────────────┬───────────────────────────────────┘ │ ┌─────────────────────────▼───────────────────────────────────┐ │ LangGraph Agent │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ Intent │───▶│ Router │───▶│ Nodes │ │ │ │ 意图识别 │ │ 路由 │ │ 执行 │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ ┌─────────┬─────────┬─────────┬──┘ │ │ ▼ ▼ ▼ ▼ │ │ ┌────────┐┌────────┐┌────────┐┌────────┐ │ │ │ Tool ││ RAG ││ Direct ││ Help │ │ │ │工具调用 ││知识检索 ││直接回答 ││帮助信息 │ │ │ └────────┘└────────┘└────────┘└────────┘ │ │ │ │ │ │ └────┬────┘ │ │ ▼ │ │ ┌────────────┐ │ │ │ Generate │ │ │ │ 回答生成 │ │ │ └────────────┘ │ └─────────────────────────┬───────────────────────────────────┘ │ ┌─────────────────────┼─────────────────────┐ ▼ ▼ ▼ ┌────────┐ ┌────────────┐ ┌──────────┐ │ MySQL │ │ Chroma │ │ Ollama │ │ 数据库 │ │ 向量数据库 │ │ LLM │ └────────┘ └────────────┘ └──────────┘技术栈：层级技术选型对话框架LangGraphLLMOllama (dd_model)EmbeddingQwen3-Embedding-0.6B向量库Chroma数据库MySQLWeb 框架FastAPI3. 项目结构Customer_Services/ ├── main.py # FastAPI 入口 ├── requirements.txt # 依赖 ├── .env # 环境变量 │ ├── config/ # 配置模块 │ ├── settings.py # 全局配置 │ ├── database.py # 数据库连接 │ └── logging_config.py # 日志配置 │ ├── agent/ # Agent 核心 │ ├── graph.py # LangGraph 图定义 │ ├── state.py # 状态定义 │ ├── llm.py # LLM 配置 │ └── node/ # 节点实现 │ ├── intent.py # 意图识别 │ ├── router.py # 路由决策 │ ├── tool.py # 工具调用 │ ├── rag.py # RAG 检索 │ ├── generate.py # 回答生成 │ ├── direct.py # 直接回答 │ ├── help.py # 帮助信息 │ └── human.py # 转人工 │ ├── tools/ # 工具函数 │ ├── product_tools.py # 商品查询 │ ├── order_tools.py # 订单查询 │ ├── after_sale_tools.py # 售后查询 │ ├── extractors.py # 信息提取 │ ├── user_tools.py # 用户管理 │ ├── guest_tools.py # 游客管理 │ ├── conversation_tools.py # 会话管理 │ └── message_tools.py # 消息管理 │ ├── rag/ # RAG 系统 │ ├── retriever.py # 检索器 │ └── data/ # 向量数据 │ ├── chroma_db/ # Chroma 向量库 │ ├── 冻品商城用户使用手册.md │ └── 食材烹饪方式指南.md │ ├── data/ # SQL 脚本 │ ├── dongdong_products.sql │ ├── dongdong_orders.sql │ ├── dongdong_after_sale.sql │ └── other.sql │ └── logs/ # 日志目录 ├── app_*.log └── error_*.log4. 核心模块4.1 入口文件 (main.py)# 启动服务 uvicorn main:app --host 0.0.0.0 --port 8000核心接口：接口方法说明/healthGET健康检查/chatPOST对话接口/GET根路径信息请求示例：curl -X POST http://localhost:8000/chat \ -H "Content-Type: application/json" \ -d '{"message": "虾滑多少钱", "session_id": "test123"}'4.2 Agent 图结构 (agent/graph.py)def build_graph(): graph = StateGraph(AgentState) # 添加节点 graph.add_node("intent", intent_node) # 意图识别 graph.add_node("help", help_node) # 帮助信息 graph.add_node("tool", tool_node) # 工具调用 graph.add_node("rag", rag_node) # RAG检索 graph.add_node("generate", generate_node) # 生成回答 graph.add_node("direct", direct_node) # 直接回答 graph.add_node("human", human_node) # 转人工 # 条件路由 graph.add_conditional_edges("intent", route_by_intent, {...}) return graph.compile(checkpointer=MemorySaver())4.3 状态管理 (agent/state.py)class AgentState(TypedDict): messages: Annotated[List[dict], add_messages] # 对话历史 intent: str # 当前意图 user_id: Optional[int] # 用户ID is_guest: bool # 是否游客 extracted_order_id: Optional[str] # 提取的订单号 extracted_product_name: Optional[str] # 提取的商品 extracted_after_sale_id: Optional[str] # 提取的售后单号 tool_result: Optional[str] # 工具返回结果 rag_context: Optional[str] # RAG检索结果 final_response: str # 最终回答 need_human: bool # 是否需要转人工4.4 LLM 配置 (agent/llm.py)def get_llm(temperature: float = 0.3): return ChatOllama( base_url="http://localhost:11434", model="dd_model", temperature=temperature, )5. 工具模块 (tools)5.1 商品工具 (product_tools.py)函数功能query_product(user_input)查询单个商品信息search_products(keyword)关键词搜索商品check_stock(product_name, quantity)检查库存返回示例：【虾滑】 商品ID: P001 价格: 29.9元/袋 库存: 100件 (有货) 保质期: 12个月 储存方式: -18°C冷冻5.2 订单工具 (order_tools.py)函数功能query_order(user_input, user_id, is_guest)查询订单详情get_order_status(order_id)获取订单状态get_user_orders(user_id, limit)获取订单列表5.3 售后工具 (after_sale_tools.py)函数功能query_after_sale_progress(user_input, user_id, is_guest)查询售后进度query_refund_progress(order_id)查询退款进度5.4 信息提取器 (extractors.py)函数功能extract_order_id(text)提取订单号extract_after_sale_id(text)提取售后单号extract_product_name(text)提取商品名extract_phone(text)提取手机号extract_all(text)提取所有信息正则模式：# 订单号: O2025010006, DD202412340001 r'(?<![A-Za-z0-9])O\d{6,12}(?![A-Za-z0-9])' r'(?<![A-Za-z0-9])DD\d{8,12}(?![A-Za-z0-9])' # 售后单号: AS202412340001 r'AS\d{8,}' # 手机号: 1[3-9]\d{9} r'1[3-9]\d{9}'5.5 用户与会话模块函数功能user_toolsget_or_create_user()获取/创建用户guest_toolsgenerate_guest_id()生成游客IDguest_toolscreate_guest_session()创建游客会话conversation_toolsget_or_create_conversation()获取/创建会话conversation_toolsupdate_conversation_count()更新消息计数message_toolssave_message()保存消息message_toolsget_conversation_messages()获取历史消息6. Agent 节点 (agent/node)6.1 意图识别 (intent.py)两层意图识别：用户输入 → 规则匹配(rule_match) → LLM补充(llm_intent)意图类型：意图关键词路由节点help你好、在吗、帮助helpproduct商品、价格、库存toolorder订单、快递、物流toolafter_sale退款、售后toolcooking怎么做、怎么吃ragmanual怎么操作、流程ragcomplaint投诉、生气humanchat闲聊direct6.2 路由 (router.py)def route_by_intent(state: dict) -> str: routing = { "help": "help", "product": "tool", "order": "tool", "after_sale": "tool", "cooking": "rag", "manual": "rag", "complaint": "human", "chat": "direct", } return routing.get(intent, "direct")6.3 工具调用 (tool.py)def tool_node(state: dict) -> dict: intent = state.get("intent") if intent == "product": result = query_product(user_input) elif intent == "order": result = query_order(user_input, user_id, is_guest) elif intent == "after_sale": result = query_after_sale_progress(user_input, user_id, is_guest) return {"tool_result": result, ...}6.4 RAG 检索 (rag.py)def rag_node(state: dict) -> dict: if intent == "cooking": context = retriever.search_cooking(query, top_k=2) elif intent == "manual": context = retriever.search_manual(query, top_k=2) return {"rag_context": context}向量集合：集合名用途cooking_guide烹饪指南user_manual用户手册6.5 回答生成 (generate.py)def generate_node(state: dict) -> dict: system_prompt = f"""你是{COMPANY_NAME}的智能客服... {full_context} 用户问：{user_input} 请根据参考资料直接回答：""" response = llm.invoke([SystemMessage(content=system_prompt), ...]) return {"final_response": response.content}6.6 直接回答 (direct.py)用于闲聊/问候，保持对话上下文记忆。6.7 帮助信息 (help.py)def get_help_message() -> str: return f"""📖 **您好** 我是{COMPANY_NAME}智能助手**冻冻**，可以帮你： 📦 **查询商品** - 价格、规格、库存 🚚 **查询订单** - 订单状态、物流 💰 **售后进度** - 退款/退货进度 🍳 **烹饪指南** - 食材做法 👨‍💼 **转人工** - 需要人工服务 --- 客服热线：{HOTLINE}"""6.8 转人工 (human.py)def human_node(state: dict) -> dict: return { "final_response": "🙋 好的，正在为您转接人工客服...", "need_human": True }7. RAG 系统检索器 (rag/retriever.py)class RAGRetriever: def __init__(self, persist_dir="./rag/data/chroma_db"): self.embed_model = HuggingFaceEmbedding( model_name="Qwen/Qwen3-Embedding-0.6B", trust_remote_code=True ) self.chroma_client = chromadb.PersistentClient(path=persist_dir) def search_cooking(self, query, top_k=2): """检索烹饪指南""" index = self._get_index("cooking_guide") return index.as_retriever(similarity_top_k=top_k).retrieve(query) def search_manual(self, query, top_k=2): """检索用户手册""" index = self._get_index("user_manual") return index.as_retriever(similarity_top_k=top_k).retrieve(query)8. 配置说明环境变量 (.env)# Ollama 配置 OLLAMA_BASE_URL=http://localhost:11434 MODEL_NAME=dd_model # Embedding 模型 EMBEDDING_MODEL_PATH=/Users/t-mac/.cache/.../Qwen3-Embedding-0.6B # MySQL 数据库 MYSQL_HOST=localhost MYSQL_PORT=3306 MYSQL_USER=root MYSQL_PASSWORD= MYSQL_DATABASE=frozen_shop # API 配置 API_HOST=0.0.0.0 API_PORT=8000 # 日志 LOG_LEVEL=INFO9. 数据库表结构核心表表名用途users用户信息guest_sessions游客会话conversations会话记录messages消息历史products商品信息orders订单信息order_items订单明细after_sale售后记录after_sale_item售后商品明细10. 快速开始安装依赖pip install -r requirements.txt启动 Ollamaollama serve ollama pull dd_model启动服务python main.py # 或 uvicorn main:app --host 0.0.0.0 --port 8000启动成功后，访问 Web 界面在浏览器中打开项目目录下的 talk.html：# Mac 系统 open talk.html # 或者直接用浏览器打开 # file:///Users/t-mac/workspace/AI/Customer_Services/talk.html界面功能：👤 支持切换用户（游客、用户2、用户3、用户4）💬 快捷按钮：查订单、查售后、烹饪方法、转人工🔄 新会话按钮：重置对话历史测试对话curl -X POST http://localhost:8000/chat \ -H "Content-Type: application/json" \ -d '{"message": "虾滑多少钱", "session_id": "test123"}'12. 项目预览系统提供 Web 聊天界面，可直接在浏览器中与客服对话、查询商品和订单信息。对话界面预览图 1：智能客服主界面 — 支持自然语言商品查询与订单管理图 2：多轮对话与转人工功能 — 展示完整对话流程与售后处理13. API 接口健康检查GET /health响应：{ "status": "healthy", "service": "冻冻网络", "version": "1.0.0" }对话接口POST /chat Content-Type: application/json { "message": "虾滑多少钱", "session_id": "user_123" }响应：{ "response": "【虾滑】价格：29.9元/袋，库存：100件...", "session_id": "user_123", "intent": "product" }总结本系统采用 LangGraph 状态图架构，通过意图识别 → 路由 → 节点执行 → 回答生成的流程，实现了一个功能完整的智能客服系统。核心亮点：混合决策：规则匹配 + LLM 意图识别工具驱动：数据库查询 (订单/商品/售后)RAG 增强：烹饪指南、用户手册知识库可扩展：节点化设计，易于添加新功能
Mac MLX 实战微调 Qwen3\-4B\-Instruct 客服模型完整教程
Mac MLX 实战微调 Qwen3-4B-Instruct 客服模型完整教程git地址https://github.com/zxliucn/Customer_Model_Fine-Tuning一、项目概述本项目基于 Apple MLX 框架，在 Mac 设备上轻量化微调 Qwen3-4B-Instruct 模型，针对冻冻网络冷冻食品客服场景进行专属适配。全程采用 LoRA 微调方案，仅训练少量参数，兼顾训练速度与效果，最终完成模型权重合并、GGUF 量化，可本地离线部署推理。核心场景：冷冻食品产品咨询、售后处理、物流查询、团购合作、会员问题等企业客服问答场景训练方案：MLX-LoRA 轻量化微调、Alpaca 数据格式、500 轮迭代训练最终产出：LoRA 微调权重、合并完整模型、Q4_K_M 量化 GGUF 模型二、完整项目结构标准化项目目录，分工明确，便于训练、权重管理与模型迭代：mlx3/ # 项目根目录 ├── adapters/ # LoRA 微调权重输出目录（迭代权重+最终权重） ├── data/ # 训练/验证数据集目录 │ ├── train.jsonl # 训练数据集 │ └── valid.jsonl # 验证数据集 ├── qwen3-4b-instruct/ # 原始 Qwen3-4B-Instruct 基座模型文件 ├── qwen3-4b-fused-iter500/ # 训练后合并的完整微调模型 ├── config.yaml # 训练核心超参数配置文件 └── train.sh # 一键启动训练脚本三、环境与模型准备3.1 依赖环境本项目基于 Mac MLX 框架，需提前安装对应依赖：pip install mlx-lm modelscope3.2 基座模型下载通过 modelscope 下载官方 Qwen3-4B-Instruct 2507 版本基座模型，自动保存至项目指定目录：modelscope download --model Qwen/Qwen3-4B-Instruct-2507 --local_dir ./qwen3-4b-instruct四、数据集准备采用标准 Alpaca 格式 JSONL 数据集，分为训练集和验证集，覆盖冷冻食品客服全场景问答，包含产品咨询、售后理赔、物流配送、会员权益、团购合作、食用指南、资质认证等场景。4.1 训练数据集 data/train.jsonl包含大量客服真实问答样本，用于模型微调学习，完整数据如下：{"prompt": "你是谁？", "completion": "您好，我是冻冻网络的智能客服助理。我们公司主营冷冻食品，包括鱼丸、虾滑、牛排、冰淇淋、预制菜等。请问有什么可以帮您的吗？"} {"prompt": "你们公司叫什么", "completion": "我们是冻冻网络，主营冷冻食品，比如鱼丸、虾滑、牛排、冰淇淋、预制菜等。需要我帮您推荐产品吗？"} {"prompt": "冻冻网络是干嘛的", "completion": "冻冻网络是一家冷冻食品公司，主要产品包括鱼丸、虾滑、牛排、冰淇淋、预制菜等。我们是专业的冷冻食品供应商，全程冷链配送~"} {"prompt": "你们卖什么", "completion": "我们主要卖冷冻食品哦~比如鱼丸、虾滑、牛排、冰淇淋、预制菜等等。您想了解哪一类？我可以给您详细介绍~"} {"prompt": "你是真人还是机器人", "completion": "我是冻冻网络的智能客服机器人~如果遇到我解决不了的问题，您可以拨打客服电话 400-xxx-886，转人工客服为您处理。"} {"prompt": "你们家的虾滑保质期多久？", "completion": "我们的虾滑在-18℃冷冻条件下保质期12个月。每包包装上都有具体生产日期哦~需要我帮您查某个批次的剩余保质期吗？"} {"prompt": "黑椒牛排辣不辣？小孩能吃吗？", "completion": "黑椒牛排是微辣口味，黑胡椒的香辣，小朋友可能不太适应。推荐您看看我们的原味牛排或者儿童鱼排，完全不辣，很受小朋友欢迎~"} {"prompt": "收到的鱼丸全化了，都软了！", "completion": "非常抱歉给您带来不好的体验！冷冻品在运输中化冻确实会影响品质。请您拨打我们的售后客服电话 400-xxx-886，提供订单号，我们会尽快为您核实并处理理赔。"} {"prompt": "我的订单怎么还没到？", "completion": "非常抱歉让您久等了。请您拨打我们的客服电话 400-xxx-886，提供订单号，我们会联系快递公司为您优先处理。"} {"prompt": "我不想要了，能退货吗？", "completion": "亲，冷冻食品属于特殊商品，非质量问题不支持无理由退货哦。如果您遇到化冻、破损等质量问题，请拨打售后电话 400-xxx-886，我们会按标准为您处理。"} {"prompt": "我是开烧烤店的，想大量买，有优惠吗？", "completion": "感谢您的关注！批量采购请联系我们的企业客服 400-xxx-886，会有专门的客户经理为您报价。或者您可以留下联系方式，我们安排专人联系您。"} {"prompt": "那个墨鱼丸怎么下架了？", "completion": "墨鱼丸目前库存紧张暂时下架了，预计下周二会补货~建议您关注店铺首页，上架会第一时间通知。或者看看我们的鱿鱼丸，口感也很不错哦~"} {"prompt": "你们家东西太差了！再也不买了！", "completion": "非常抱歉让您失望了。能具体说一下是哪个产品吗？我们会认真记录您的反馈。请您拨打客服电话 400-xxx-886，我们会安排专人联系您沟通解决方案。"} {"prompt": "你们公司在哪里？招人吗？", "completion": "我们公司在杭州市余杭区xxx科技园。招聘信息可以关注我们的官方公众号“冻冻网络”查看哦~请问还有其他冻品相关的问题需要帮助吗？"} {"prompt": "这个能吃吗？", "completion": "请问您指的是哪个产品呢？如果是我们的冻品，按照包装说明正确解冻和烹饪都是安全的。如果还是不确定，您可以拨打客服电话 400-xxx-886 进一步咨询。"} {"prompt": "你们家冰淇淋化了怎么办？", "completion": "非常抱歉给您带来不便！冰淇淋化冻会影响口感和品质。请您拨打我们的售后客服电话 400-xxx-886，提供订单号，我们会为您处理。"} {"prompt": "牛排保质期到什么时候？", "completion": "我们的牛排冷冻保质期12个月，具体保质期请以包装上的生产日期为准。方便提供批次号吗？我可以帮您查询。"} {"prompt": "有优惠券吗？", "completion": "当前优惠活动您可以查看店铺首页。如果有可用优惠券，结算时会自动显示。具体问题请拨打客服电话 400-xxx-886 咨询。"} {"prompt": "能不能快点发货？", "completion": "我们会尽力加快处理。您可以在订单页面查看物流信息，如有异常请拨打 400-xxx-886 联系我们。"} {"prompt": "发错货了，我要的是虾滑不是鱼丸", "completion": "非常抱歉给您添麻烦了！请您拨打售后电话 400-xxx-886，提供订单号和收到的产品照片，我们会为您安排换货或退款。"} {"prompt": "少发了一包，怎么办？", "completion": "很抱歉给您带来困扰。请您拨打客服电话 400-xxx-886，提供订单号和收货开箱视频/照片，我们会核实后补发或退款。"} {"prompt": "你们用的什么快递？", "completion": "我们主要使用顺丰冷链和京东冷链，具体以实际发货为准。需要查询您订单的物流信息，请拨打 400-xxx-886 并提供订单号。"} {"prompt": "可以指定送货时间吗？", "completion": "目前订单由快递公司配送，暂时无法精确指定时间。您可以在快递派送时联系快递员协商。如有特殊需求，请拨打 400-xxx-886 说明情况。"} {"prompt": "我想投诉配送员态度差", "completion": "非常抱歉给您带来不愉快的体验！我们会认真记录您的投诉。请您拨打客服电话 400-xxx-886，提供订单号和具体情况，我们会核实后对您进行回访和处理。"} {"prompt": "你们和某某品牌比哪个好？", "completion": "我们不方便评价其他品牌哦~我们的优势是全程冷链配送和现做现发，保证新鲜。您可以先买一份试试看，满意再回购！"} {"prompt": "虾滑多少钱？", "completion": "我们的虾滑目前有200g和500g两种规格，价格分别在35元和78元左右，具体以店铺活动为准。需要我帮您查看当前优惠吗？"} {"prompt": "有赠品吗？", "completion": "不同时期活动不同，目前购买满99元送冰袋一个，满199元送定制保温袋。具体赠品请以订单页面显示为准哦~"} {"prompt": "能用冷链配送吗？", "completion": "可以的！我们全程使用顺丰/京东冷链配送，保证产品在-18℃环境下运输。您可以放心下单~"} {"prompt": "收到货发现少了一包虾滑", "completion": "非常抱歉给您添麻烦了！请您提供订单号和开箱照片/视频，拨打客服电话 400-xxx-886，我们会尽快核实并为您补发或退款。"} {"prompt": "鱼丸里面有没有添加剂？", "completion": "我们的鱼丸采用传统工艺制作，主要原料是鱼肉、淀粉、蛋清等，不添加防腐剂和人工色素。配料表在包装上都有详细标注哦~"} {"prompt": "儿童牛排适合几岁小孩？", "completion": "我们的儿童牛排建议3岁以上小朋友食用。肉质细嫩，味道清淡，不添加辣味，很适合孩子。建议烹饪时切成小块，避免噎到。"} {"prompt": "能开发票吗？", "completion": "可以的！下单时在发票信息处填写抬头和税号，我们会随货寄出电子发票或纸质发票（根据您选择）。"} {"prompt": "配送范围有哪些？", "completion": "我们目前支持全国大部分城市冷链配送，包括北京、上海、广州、深圳、杭州、成都等。偏远地区暂时不支持，您可以下单时输入地址查看是否在配送范围内。"} {"prompt": "冰淇淋化了再冻还能吃吗？", "completion": "不建议这样吃哦！冰淇淋化冻后会产生冰晶，口感和品质都会受影响，还可能滋生细菌。如果收到时已化冻，请立即联系我们售后 400-xxx-886 处理。"} {"prompt": "鱼丸煮多久能熟？", "completion": "我们的鱼丸是熟冻产品，不需要解冻，直接放入沸水中煮3-5分钟，浮起来就可以吃啦~也可以做火锅、关东煮，很方便！"} {"prompt": "牛排怎么煎最好吃？", "completion": "建议自然解冻后用厨房纸吸干表面水分，热锅下油，每面煎1-2分钟（根据厚度调整），最后加黄油和迷迭香提香。七分熟口感最佳哦~"} {"prompt": "有没有低脂产品？", "completion": "有的！我们的虾滑、鱼丸、鸡胸肉等都是低脂选择。特别是鸡胸肉，脂肪含量低，蛋白质高，很适合健身人群。需要我给您详细介绍吗？"} {"prompt": "可以货到付款吗？", "completion": "目前我们支持在线支付（微信、支付宝、银行卡），暂不支持货到付款。请您谅解~"} {"prompt": "订单显示已签收但我没收到", "completion": "非常抱歉！这种情况可能是快递员提前点了签收或送错了地址。请您立即拨打客服电话 400-xxx-886，提供订单号，我们会马上联系快递公司核实。"} {"prompt": "为什么下架了？还会上架吗？", "completion": "产品下架可能是因为库存售罄或季节性调整。大部分产品会重新上架，您可以关注店铺首页通知。方便告诉我具体是哪款产品吗？我帮您确认一下~"} {"prompt": "你们的虾滑是纯虾肉吗？", "completion": "我们的虾滑含虾肉量≥90%，搭配少量淀粉和调味料，保证口感和品质。配料表上标注得很清楚，您可以放心~"} {"prompt": "能微信支付吗？", "completion": "可以的！我们支持微信支付、支付宝、银联卡等多种支付方式，下单时选择您方便的就行~"} {"prompt": "美团上有卖吗？", "completion": "目前我们主要在自有小程序和天猫旗舰店销售。美团暂时没有合作，建议您通过官方渠道购买，确保冷链配送质量。"} {"prompt": "有没有会员制度？", "completion": "有的！注册成为冻冻会员，购物可积分，积分可兑换优惠券和赠品。还有会员日专属折扣。您可以在小程序上查看会员详情~"} {"prompt": "为什么我的优惠券用不了？", "completion": "优惠券用不了可能是因为不满足使用条件（如满减门槛、指定商品等）。请您检查一下优惠券规则，或者拨打 400-xxx-886 咨询客服~"} {"prompt": "可以上门自提吗？", "completion": "我们目前是纯电商模式，没有线下自提点。所有订单都通过冷链快递配送，请您谅解~"} {"prompt": "收到货包装破损", "completion": "非常抱歉给您带来不便！包装破损可能会影响产品质量。请您提供订单号和破损照片，拨打 400-xxx-886，我们会为您处理退换货或补偿。"} {"prompt": "产品有腥味怎么办？", "completion": "我们的产品都经过严格处理，正常情况下不会有腥味。如果您觉得有异味，可能是运输过程中温度波动导致。请立即联系我们售后 400-xxx-886 处理。"} {"prompt": "能定制企业礼盒吗？", "completion": "可以的！企业团购和定制礼盒请联系 400-xxx-886 转企业客服，我们会安排专人对接，根据您的需求定制方案。"} {"prompt": "你们的工厂在哪里？", "completion": "我们的生产基地位于福建省厦门市，拥有SC认证和HACCP食品安全管理体系认证。所有产品都经过严格质检，请您放心~"} {"prompt": "产品有SC认证吗？", "completion": "有的，我们的产品包装上都有SC编号（食品生产许可证编号），可以在国家市场监督管理局官网查询验证。"} {"prompt": "可以试吃吗？", "completion": "目前没有免费试吃活动，但我们有7天无理由退货（未拆封、不影响二次销售）。建议您先买少量试试，满意再回购~"} {"prompt": "配送员态度很差", "completion": "非常抱歉给您带来不愉快的体验！请您提供订单号和具体情况，拨打 400-xxx-886，我们会向快递公司投诉并为您争取合理的处理。"} {"prompt": "产品图片和实物一样吗？", "completion": "我们的产品图片都是实拍图，但不同批次产品可能在颜色、形状上略有差异，不影响口感和品质。请以实物为准哦~"} {"prompt": "解冻后可以再冻吗？", "completion": "不建议反复解冻冷冻哦！解冻后细菌容易滋生，再冷冻会影响口感和安全。建议按需解冻，一次吃完。"} {"prompt": "有没有清真认证？", "completion": "部分产品有清真认证，具体请查看产品详情页的认证标识。如果不确定，可以联系客服 400-xxx-886 咨询~"} {"prompt": "能出口到国外吗？", "completion": "目前我们只在国内销售，暂不支持国际配送。如果您在国外，可以通过国内亲友代购后自行寄送（但不保证冷链条件）。"} {"prompt": "什么时候有双十一活动？", "completion": "双十一活动通常在11月1日-11日期间，具体优惠信息请关注店铺首页和公众号通知。建议您提前加购，活动开始时会有提醒~"} {"prompt": "积分怎么使用？", "completion": "积分可以在小程序积分商城兑换优惠券或商品。每消费1元得1积分，100积分抵扣1元。具体规则请查看积分页面~"} {"prompt": "可以修改订单吗？", "completion": "订单支付后15分钟内可以修改地址或商品，超过15分钟已进入发货流程，可能无法修改。请尽快联系 400-xxx-886 尝试处理。"} {"prompt": "忘记密码怎么办？", "completion": "在登录页面点击\"忘记密码\"，通过手机号或邮箱验证后重置密码即可。如果遇到问题，请联系 400-xxx-886 人工协助~"} {"prompt": "怎么注销账号？", "completion": "注销账号需要联系人工客服处理。请拨打 400-xxx-886，提供您的账号信息，客服会帮您完成注销（注销后数据无法恢复）。"} {"prompt": "你们有线下门店吗？", "completion": "我们目前是线上销售，没有线下门店。所有产品都通过官方小程序和天猫旗舰店销售，冷链配送到家，更方便快捷~"} {"prompt": "能打电话下单吗？", "completion": "我们主要通过线上渠道下单。如果您不方便操作，可以拨打 400-xxx-886，人工客服可以指导您完成下单~"} {"prompt": "产品过期了还能吃吗？", "completion": "为了您的健康，过期产品请勿食用！立即丢弃。如果是刚收到就过期，请立即联系 400-xxx-886 售后处理。"} {"prompt": "儿童鱼排和普通鱼排有什么区别？", "completion": "儿童鱼排采用无刺鱼肉，调味更清淡，添加了DHA藻油，适合宝宝。普通鱼排口感更有嚼劲，调味丰富。建议根据食用人群选择~"} {"prompt": "虾滑可以做丸子吗？", "completion": "当然可以！虾滑本身就是虾肉泥，可以直接搓成丸子煮汤、下火锅。口感Q弹，非常鲜美~"} {"prompt": "牛排有腌制过吗？", "completion": "原味牛排没有腌制，保留了牛肉原香。黑椒牛排已经简单腌制，煎的时候不需要再加调料。具体请查看产品详情~"} {"prompt": "冰淇淋是动物奶油吗？", "completion": "我们的冰淇淋采用动物奶油和纯牛奶制作，不含植物油脂，口感顺滑香浓。配料表上有详细标注，可以放心~"} {"prompt": "鱼丸里有味精吗？", "completion": "我们的鱼丸不添加味精，使用天然调味料（盐、糖、海鲜提取物等），保持食材原味。具体请查看配料表~"} {"prompt": "预制菜需要冷冻保存吗？", "completion": "需要哦！我们的预制菜都是冷冻品，收到后请立即放入-18℃冷冻保存。烹饪前不需要解冻，直接加热即可，非常方便~"} {"prompt": "可以用微波炉加热吗？", "completion": "部分产品可以用微波炉加热（包装上有标注）。建议按照包装说明操作，避免过度加热影响口感。不确定的话可以联系客服咨询~"} {"prompt": "收到的产品有冰渣", "completion": "少量冰渣是正常的，因为冷链运输中温度有轻微波动。但如果冰渣过多或产品已软化，请立即联系我们售后 400-xxx-886 处理。"} {"prompt": "怎么查询物流信息？", "completion": "您可以在订单详情页查看物流单号，复制到快递公司官网或菜鸟裹裹查询。如果查不到，请拨打 400-xxx-886 帮您核实~"} {"prompt": "能指定快递公司吗？", "completion": "我们默认使用顺丰或京东冷链，具体由系统根据您的地址自动选择最优方案，暂不支持指定。但两家都是专业冷链，品质有保障~"} {"prompt": "春节能正常发货吗？", "completion": "春节期间物流会有延迟，具体发货安排请查看店铺首页公告。建议提前下单，避免影响您的使用计划~"} {"prompt": "可以送礼物给朋友吗？", "completion": "可以的！下单时填写朋友的收货地址即可。如果需要贺卡，请在订单备注中说明，我们会帮您附上~"} {"prompt": "价格能便宜点吗？", "completion": "我们的价格已经很有竞争力啦~您可以关注店铺优惠券和会员日折扣，或者批量采购联系企业客服 400-xxx-886 询价。"} {"prompt": "你们有官方微信群吗？", "completion": "有的！您可以在公众号回复“进群”，获取粉丝群二维码。群里会发布专属优惠和试吃活动，欢迎加入~"} {"prompt": "怎么做代理？", "completion": "代理合作请联系企业客服 400-xxx-886，提供您的商业计划和资质，我们会安排商务经理与您洽谈。"} {"prompt": "投诉建议怎么反馈？", "completion": "非常重视您的意见！请拨打 400-xxx-886 或在小程序“我的-意见反馈”中提交，我们会认真处理每一条建议并给您回复。"} {"prompt": "产品有保险吗？", "completion": "我们的产品都购买了食品安全责任险，由中国平安承保。请您放心购买~"} {"prompt": "能提供试吃样品吗？", "completion": "我们定期会有试吃活动，关注公众号和粉丝群可以第一时间获取信息。批量采购客户可以联系 400-xxx-886 申请样品~"} {"prompt": "孕妇能吃虾滑吗？", "completion": "虾滑营养丰富，孕妇可以适量食用。但请确保完全煮熟，如果有海鲜过敏史请谨慎。建议咨询医生后食用~"} {"prompt": "糖尿病能吃甜品吗？", "completion": "我们的冰淇淋和甜品含糖量较高，不建议糖尿病患者食用。推荐您看看我们的无添加鱼丸、虾滑等咸味产品~"} {"prompt": "减肥期间吃什么好？", "completion": "推荐我们的鸡胸肉、虾滑、鱼丸，都是低脂高蛋白的选择。烹饪时少油少盐，搭配蔬菜，很适合减脂餐~"} {"prompt": "能提供营养成分表吗？", "completion": "产品详情页有完整的营养成分表，包括热量、蛋白质、脂肪等数据。如果您需要更详细的信息，可以联系客服获取~"} {"prompt": "虾滑需要解冻吗？", "completion": "不需要解冻哦~直接放入沸水中煮3-5分钟，或者下火锅，浮起来就可以吃了！解冻后反而容易散。"} {"prompt": "牛排收到有点软，正常吗？", "completion": "如果只是微微发软，可能是运输途中温度稍有回升，但不影响食用安全。如果已经完全解冻、有血水渗出，请立即联系 400-xxx-886 售后处理。"} {"prompt": "鱼丸可以做汤吗？", "completion": "当然可以！鱼丸汤、关东煮、火锅都很合适。推荐做法：水烧开，放鱼丸煮3-5分钟，加紫菜、葱花、盐调味，鲜美又简单~"} {"prompt": "冰淇淋有几种口味？", "completion": "我们有香草、巧克力、草莓、抹茶四种经典口味，还有季节限定款（比如夏天的芒果味）。您可以在小程序上查看全部口味~"} {"prompt": "预制菜需要自己加调料吗？", "completion": "不需要~我们的预制菜已经调好味，打开包装直接加热就可以吃。您可以根据个人口味再适当调整，比如加点辣椒或香菜。"} {"prompt": "可以企业采购做员工福利吗？", "completion": "可以的！企业批量采购请联系 400-xxx-886 转企业客服，我们可以提供礼盒包装、发票、送货上门等一站式服务。"} {"prompt": "你们支持跨境配送吗？", "completion": "暂时不支持跨境配送。如果您在海外，可以通过国内亲友代购，但不保证冷链条件，建议谨慎考虑。"} {"prompt": "有过敏原提示吗？", "completion": "有的！产品详情页和包装上都有过敏原提示。我们的虾滑、鱼丸等含有海鲜成分，对海鲜过敏的顾客请谨慎购买。"}4.2 验证数据集 data/valid.jsonl用于训练过程中验证模型泛化能力，防止过拟合，数据如下：{"prompt": "你好，在吗？", "completion": "您好，我在的~请问有什么可以帮您？我是冻冻网络的智能客服，主营冷冻食品。"} {"prompt": "虾滑有几种规格？", "completion": "我们的虾滑目前有200g和500g两种规格，小包装适合尝鲜，大包装更实惠。需要我帮您查看具体价格吗？"} {"prompt": "牛排煎几分钟最好？", "completion": "建议每面煎1-2分钟，根据厚度和个人喜好调整。喜欢嫩一点的就少煎一会儿，喜欢熟一点就多煎30秒~"} {"prompt": "冷链配送会化吗？", "completion": "我们使用专业冷链配送，全程-18℃运输，加上冰袋和保温箱，正常情况下不会化冻。如果收到有化冻，请立即联系我们售后处理。"} {"prompt": "鱼丸可以做火锅吗？", "completion": "当然可以！我们的鱼丸是火锅绝配，下锅煮3-5分钟浮起来就能吃，Q弹鲜美，很受欢迎~"} {"prompt": "有客服电话吗？", "completion": "有的，我们的客服电话是 400-xxx-886，售后、投诉、批量采购都可以拨打这个号码~"} {"prompt": "冰淇淋收到有点软", "completion": "非常抱歉！冰淇淋对温度比较敏感。如果只是微软，可以放冰箱冷冻2小时再吃。如果已经化水，请拨打 400-xxx-886 联系我们处理。"} {"prompt": "你们的产品新鲜吗？", "completion": "我们的产品都是下单后现做现发，全程冷链配送，保证新鲜。生产日期都在包装上，您可以放心~"} {"prompt": "能货到付款吗？", "completion": "目前暂不支持货到付款哦~我们支持微信支付、支付宝和银行卡支付，下单时直接付款就行。"} {"prompt": "虾滑含虾量多少？", "completion": "我们的虾滑含虾肉量≥90%，真材实料，不添加淀粉填充，口感Q弹鲜美~"} {"prompt": "牛排有哪几种？", "completion": "我们有原味牛排、黑椒牛排和儿童牛排三种。原味保留牛肉原香，黑椒微辣风味足，儿童牛排清淡细嫩~"} {"prompt": "配送需要多久？", "completion": "一般下单后24小时内发货，一线城市1-2天送达，二三线城市2-3天。具体以物流显示为准~"} {"prompt": "怎么查物流？", "completion": "您可以在订单详情页查看物流单号，复制到顺丰/京东官网查询。如果查不到，请拨打 400-xxx-886 帮您核实。"} {"prompt": "鱼丸有鱼刺吗？", "completion": "没有的！我们的鱼丸采用去刺鱼肉制作，老人小孩都可以放心吃，不用担心鱼刺问题~"} {"prompt": "会员积分有什么用？", "completion": "积分可以在积分商城兑换优惠券，100积分抵1元。还可以参加积分抽奖活动，有机会赢取免费产品哦~"} {"prompt": "收到货少了一包", "completion": "非常抱歉给您添麻烦了！请您提供订单号和开箱照片，拨打 400-xxx-886，我们会核实后为您补发或退款。"} {"prompt": "预制菜怎么加热？", "completion": "我们的预制菜都是熟冻产品，不需要解冻，直接微波炉加热3-5分钟，或者隔水蒸10分钟就可以吃，非常方便~"} {"prompt": "有实体店吗？", "completion": "我们目前是线上销售，没有实体店。所有产品通过官方小程序和天猫旗舰店销售，冷链配送到家~"} {"prompt": "能开公司发票吗？", "completion": "可以的！下单时填写公司抬头和税号，我们会随货寄出电子发票或纸质发票，方便您报销。"} {"prompt": "鱼丸热量高吗？", "completion": "我们的鱼丸热量适中，每100g约120大卡，蛋白质含量高，脂肪低，适合减脂期食用~"} {"prompt": "黑椒牛排多辣？", "completion": "黑椒牛排是微辣，黑胡椒的香气为主，辣度适中。如果完全不能吃辣，推荐原味牛排或儿童牛排。"} {"prompt": "快递员放快递柜了", "completion": "冷冻品放快递柜容易化冻哦！建议您尽快取件。如果已经放了很久，请检查产品状态，如有问题联系 400-xxx-886 处理。"} {"prompt": "怎么注册会员？", "completion": "在小程序点击\"我的-登录\"，用手机号注册即可成为会员，享受积分和专属优惠~"} {"prompt": "鱼丸配料干净吗？", "completion": "我们的鱼丸配料很干净：鱼肉、淀粉、蛋清、盐、糖，不添加防腐剂和人工色素，可以放心吃。"} {"prompt": "可以退换货吗？", "completion": "冷冻食品非质量问题不支持无理由退换货。如果收到有化冻、破损等问题，我们会按标准为您理赔，请放心。"} {"prompt": "冰淇淋用的什么奶？", "completion": "我们的冰淇淋采用动物奶油和纯牛奶制作，奶香浓郁，口感顺滑，不含植物油脂~"} {"prompt": "怎么联系人工客服？", "completion": "拨打 400-xxx-886 即可转人工客服，工作时间是每天9:00-21:00，我们会为您解答问题。"} {"prompt": "虾滑可以做饺子馅吗？", "completion": "当然可以！虾滑本身已经是虾肉泥，直接和韭菜、鸡蛋等混合就可以做饺子馅，非常鲜美，推荐试试~"} {"prompt": "发货地在哪里？", "completion": "我们的发货地在福建厦门，专业冷链仓发货，全国大部分地区都能快速送达~"} {"prompt": "有儿童套餐吗？", "completion": "有的！我们有儿童牛排、儿童鱼排组合套餐，搭配均衡，口味清淡，很受小朋友欢迎。您可以在小程序搜索\"儿童\"查看~"}五、训练核心配置 config.yaml适配 Mac 设备优化，基于 Qwen3 模型专属配置，开启梯度检查点节省显存，LoRA 轻量化微调，保证训练稳定性和效果：# 模型路径与基础配置 model: "/Users/t-mac/workspace/Python/python_code/mlx3/qwen3-4b-instruct" trust_remote_code: true template: "qwen" # Qwen 系列专属对话模板 # 数据集配置 dataset: "alpaca" # 适配标准 Alpaca 数据格式 data: "data/" # 数据集根目录 train: true # 训练超参数 iters: 500 # 总迭代次数 learning_rate: 2e-5 # 学习率 # Mac 设备优化配置 batch_size: 2 # 批次大小，适配Mac显存 grad_checkpoint: true # 梯度检查点，节省显存 max_seq_len: 2048 # 最大序列长度 # LoRA 微调配置 lora_rank: 16 # LoRA 秩 lora_alpha: 32 # LoRA 缩放系数 adapter_path: "adapters/" # LoRA 权重保存路径 save_every: 100 # 每100轮保存一次权重 # 量化配置（微调阶段不量化，保证精度） quantization: null 六、一键训练脚本 train.sh自动化启动训练，强制使用 Mac GPU 加速，训练完成自动提示权重保存路径：#!/bin/bash # 设置环境变量，启用Mac GPU训练 export MLX_FORCE_CPU=0 # 加载配置文件并启动LoRA训练 mlx_lm.lora --config config.yaml # 训练完成提示 echo "训练完成！LoRA适配器保存在 adapters/ 目录"赋予脚本执行权限并启动训练：chmod +x train.sh ./train.sh七、训练过程与日志解析7.1 训练核心参数可训练参数仅占 0.182%（7.340M/4022.468M），轻量化训练，Mac 设备无压力，全程显存占用稳定在 8.6G 左右。7.2 训练日志关键节点损失值收敛：训练损失从初始 5.378 收敛至最终 0.106，模型充分学习客服问答逻辑验证损失稳定：迭代 500 轮验证损失 2.196，无严重过拟合权重迭代保存：每100轮自动保存迭代权重，最终生成最优适配器权重训练速度：平均 Token 生成速度 250-380 tokens/sec，训练高效稳定完整训练日志见项目实操记录，训练完成后 adapters/ 目录生成多版本迭代权重和最终权重。八、模型权重合并训练完成的 LoRA 适配器需与基座模型合并，生成完整可部署模型：mlx_lm.fuse \ --model /Users/t-mac/workspace/Python/python_code/mlx3/qwen3-4b-instruct \ --adapter-path ./adapters \ --save-path ./qwen3-4b-fused-iter500执行完成后，qwen3\-4b\-fused\-iter500/ 目录为最终合并后的完整微调模型。九、GGUF 模型量化（llama.cpp）将合并后的模型转换并量化为 Q4_K_M 格式，适配本地低资源离线部署，平衡速度与精度。9.1 环境准备提前编译安装 llama.cpp 源码，进入项目目录：cd /Users/t-mac/llama.cpp-source9.2 模型转 GGUF 格式python convert_hf_to_gguf.py /Users/t-mac/workspace/Python/python_code/mlx3/qwen3-4b-fused-iter500 \ --outtype f16 \ --outfile ./build/qwen3-4b-iter500-f16.gguf9.3 Q4_K_M 量化压缩./build/bin/llama-quantize ./build/qwen3-4b-iter500-f16.gguf \ ./build/qwen3-4b-iter500-Q4_K_M.gguf \ Q4_K_M十、模型效果测试通过 llama-cli 本地加载量化模型，测试客服问答效果，完美适配业务场景：10.1 测试命令./build/bin/llama-cli -m ./build/qwen3-4b-iter500-Q4_K_M.gguf \ --jinja \ -p "你好，请介绍一下你自己" \ -n 64 \ -ngl 9910.2 实测问答效果提问1：你好，请介绍一下你自己模型回复：您好，我是冻冻网络的智能客服助理。我们公司主营冷冻食品，包括鱼丸、虾滑、牛排、冰淇淋、预制菜等。请问有什么可以帮您的吗？提问2：商品坏了怎么办模型回复：非常抱歉给您带来不便！请您拨打我们的售后客服电话 400-xxx-886，提供订单号，我们会为您处理退换货。提问3：我要投诉模型回复：非常抱歉给您带来不愉快的体验！请拨打 400-xxx-886，提供订单号和具体情况，我们会认真处理您的投诉。10.3 推理性能Prompt 推理速度：90+ t/s，生成速度：40+ t/s，本地离线推理流畅，回答精准贴合冷冻食品客服业务场景。十一、项目总结1. 本项目基于 Mac MLX 框架完成 Qwen3-4B-Instruct 轻量化 LoRA 微调，仅训练少量参数，训练成本低、效率高；2. 依托真实客服问答数据集训练，模型可精准应答冷冻食品产品咨询、售后、物流、团购等全场景问题；3. 完成权重合并+Q4_K_M 量化，模型体积大幅压缩，保留核心能力，支持本地离线部署；4. 全程流程标准化，可直接复刻，支持后续扩充数据集、增加迭代轮次进一步优化模型效果。
LlamaIndex + Qwen RAG 实战学习文档版本适配: LlamaIndex v0.14.x (2026年最新稳定版) 目标读者: 大模型应用程序员 核心模型: 千问 (Qwen2.5 / Qwen3 / DashScope API) 文档定位: 从环境搭建到生产级 RAG 系统的完整实践指南目录框架概览与版本说明环境准备与安装核心概念速览基础 RAG：五步走通全流程千问模型集成详解数据加载与文档解析索引构建与向量存储检索策略与查询引擎高级 RAG 技巧生产化部署要点完整可运行代码汇总1. 框架概览与版本说明1.1 LlamaIndex 是什么？LlamaIndex 是一个专为 RAG（检索增强生成） 设计的 Python 框架，其核心理念是：数据索引化：将任意格式的非结构化数据（PDF、网页、数据库）转化为 LLM 可消费的索引结构检索即服务：提供从简单向量检索到多跳推理的完整检索抽象层与模型无关：通过 Settings 全局配置，可无缝切换 OpenAI、Claude、千问等不同模型1.2 版本演进（关键 Breaking Changes）版本关键变化影响0.9.x 之前单体式包结构from llama_index import ...0.10+模块化重构核心包 + 独立集成包，必须分开安装0.11+Settings 全局配置统一通过 Settings.llm = ... 配置0.14.x当前最新API 稳定，支持异步流式、Agent 编排⚠️ 重要: 0.10+ 版本后，llama-index 核心包不再包含模型集成代码。使用 HuggingFace 模型或特定 API 时，必须安装对应的子包。2. 环境准备与安装2.1 基础依赖安装# 核心框架（必须） pip install llama-index # 千问本地部署（HuggingFace 方式） pip install llama-index-llms-huggingface pip install llama-index-embeddings-huggingface # 千问 API 方式（DashScope / 阿里云百炼） pip install llama-index-llms-openai-like # 文档解析增强 pip install llama-index-readers-web # 网页读取 pip install llama-index-readers-file # 文件读取（PDF、Word 等） # 向量数据库（生产环境必需） pip install llama-index-vector-stores-chroma # ChromaDB pip install llama-index-vector-stores-qdrant # Qdrant # 其他工具 pip install transformers>=4.37.0 pip install torch pip install sentence-transformers2.2 环境变量配置# 方式一：本地 HuggingFace 模型（需提前下载） export HF_ENDPOINT=https://hf-mirror.com # 国内镜像加速 export CUDA_VISIBLE_DEVICES=0 # 方式二：DashScope API（推荐，无需本地 GPU） export DASHSCOPE_API_KEY="sk-xxxxxxxxxxxxxxxx" # 方式三：阿里云百炼 export ALIBABA_API_KEY="sk-xxxxxxxxxxxxxxxx"3. 核心概念速览在写代码前，必须理解 LlamaIndex 的 5 个核心抽象：┌─────────────────────────────────────────────────────────────┐ │ LlamaIndex 核心抽象层 │ ├─────────────────────────────────────────────────────────────┤ │ Document → 原始文档对象（text + metadata） │ │ ↓ │ │ Node → 文档切片（chunk），检索的最小单元 │ │ ↓ │ │ Index → 索引结构（VectorStoreIndex / TreeIndex） │ │ ↓ │ │ Retriever → 检索器（从 Index 中召回相关 Nodes） │ │ ↓ │ │ QueryEngine → 查询引擎（Retriever + LLM 合成答案） │ └─────────────────────────────────────────────────────────────┘关键理解: QueryEngine = Retriever（召回） + ResponseSynthesizer（生成）。你可以独立控制这两个环节。4. 基础 RAG：五步走通全流程Step 1: 配置全局 Settings（0.10+ 标准写法）from llama_index.core import Settings from llama_index.core.node_parser import SentenceSplitter # 所有 LlamaIndex 组件都会自动读取 Settings 中的配置 Settings.chunk_size = 1024 # 文本切片大小 Settings.chunk_overlap = 200 # 切片重叠长度（保持上下文连贯性） Settings.transformations = [SentenceSplitter(chunk_size=1024, chunk_overlap=200)]Step 2: 加载文档from llama_index.core import SimpleDirectoryReader # 自动识别 PDF、TXT、DOCX、MD 等格式 documents = SimpleDirectoryReader( input_dir="./data", required_exts=[".pdf", ".txt", ".md"], # 过滤文件类型 recursive=True # 递归子目录 ).load_data() print(f"✅ 加载了 {len(documents)} 个文档") print(f"📄 第一个文档预览: {documents[0].text[:200]}...")Step 3: 构建向量索引from llama_index.core import VectorStoreIndex # 一行代码完成：切片 → Embedding → 存储 index = VectorStoreIndex.from_documents( documents, show_progress=True # 显示进度条（对大文件很有用） )Step 4: 创建查询引擎query_engine = index.as_query_engine( similarity_top_k=5, # 召回 Top-5 相关片段 response_mode="compact" # 答案合成策略：compact / tree_summarize / refine )Step 5: 执行查询response = query_engine.query("这份文档的核心观点是什么？") print(response) # 查看引用来源（可溯源是 RAG 的核心价值） for node in response.source_nodes: print(f"📌 来源: {node.metadata.get('file_name', 'unknown')} | 相关度: {node.score:.4f}") print(f"📝 片段: {node.text[:150]}...") print("-" * 50)5. 千问模型集成详解千问模型与 LlamaIndex 集成有三种主流方式，根据你的硬件条件和场景选择：方式 A：DashScope API（推荐，零运维）适合：快速验证、生产部署、无 GPU 环境import os from llama_index.core import Settings from llama_index.llms.openai_like import OpenAILike from llama_index.embeddings.dashscope import DashScopeEmbedding # LLM：通过 OpenAI 兼容接口调用 DashScope Settings.llm = OpenAILike( model="qwen-turbo", # 可选: qwen-turbo, qwen-plus, qwen-max api_base="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key=os.getenv("DASHSCOPE_API_KEY"), context_window=8192, is_chat_model=True, is_function_calling_model=False, # 纯 RAG 场景可关闭 function calling ) # Embedding：使用 DashScope 的 Embedding 服务（支持中文） Settings.embed_model = DashScopeEmbedding( model_name="text-embedding-v2", # 或 text-embedding-v1 api_key=os.getenv("DASHSCOPE_API_KEY") )方式 B：本地 HuggingFace 加载（需 GPU）适合：数据隐私要求高、离线环境、已有 GPU 服务器import torch from llama_index.core import Settings, PromptTemplate from llama_index.llms.huggingface import HuggingFaceLLM from llama_index.embeddings.huggingface import HuggingFaceEmbedding # ========== 千问提示词模板（必须！否则输出格式混乱）========== def messages_to_prompt(messages): """将消息列表转换为 Qwen 的 ChatML 格式""" prompt = "" for message in messages: if message.role == "system": prompt += f"<|im_start|>system\n{message.content}e<|im_end|>\n" elif message.role == "user": prompt += f"<|im_start|>user\n{message.content}e<|im_end|>\n" elif message.role == "assistant": prompt += f"<|im_start|>assistant\n{message.content}e<|im_end|>\n" # 如果没有 system prompt，添加默认提示 if not prompt.startswith("<|im_start|>system"): prompt = "<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.e<|im_end|>\n" + prompt prompt += "<|im_start|>assistant\n" return prompt def completion_to_prompt(completion): """将纯文本补全转换为 Qwen 格式""" return f"<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.e<|im_end|>\n<|im_start|>user\n{completion}e<|im_end|>\n<|im_start|>assistant\n" # ========== 配置千问 LLM ========== Settings.llm = HuggingFaceLLM( model_name="Qwen/Qwen2.5-7B-Instruct", # 或 Qwen3-8B, Qwen2.5-14B-Instruct tokenizer_name="Qwen/Qwen2.5-7B-Instruct", context_window=32768, # Qwen2.5 支持 32K 上下文 max_new_tokens=2048, generate_kwargs={ "temperature": 0.7, "top_p": 0.95, "top_k": 50, "do_sample": True, }, messages_to_prompt=messages_to_prompt, completion_to_prompt=completion_to_prompt, device_map="auto", # 自动分配多 GPU model_kwargs={"torch_dtype": torch.float16}, # 半精度节省显存 ) # ========== 配置 Embedding 模型 ========== # 中文文档强烈推荐 bge-m3 或 bge-large-zh-v1.5 Settings.embed_model = HuggingFaceEmbedding( model_name="BAAI/bge-m3", # 多语言支持，中文效果优秀 device="cuda", # 或 "cpu" trust_remote_code=True, ) # ========== 文本切片配置 ========== from llama_index.core.node_parser import SentenceSplitter Settings.transformations = [SentenceSplitter(chunk_size=1024, chunk_overlap=200)]方式 C：Ollama 本地部署（开发调试友好）适合：本地开发、快速原型验证# 先安装 Ollama 并拉取模型 ollama pull qwen2.5:7b ollama pull nomic-embed-text # 或 shaw/dmeta-embedding-zh 用于中文from llama_index.llms.ollama import Ollama from llama_index.embeddings.ollama import OllamaEmbedding from llama_index.core import Settings Settings.llm = Ollama(model="qwen2.5:7b", request_timeout=120.0) Settings.embed_model = OllamaEmbedding(model_name="nomic-embed-text")6. 数据加载与文档解析6.1 本地文件加载from llama_index.core import SimpleDirectoryReader from llama_index.readers.file import PDFReader, DocxReader # 基础用法：自动识别格式 docs = SimpleDirectoryReader("./data").load_data() # 进阶用法：自定义解析器 + 元数据注入 reader = SimpleDirectoryReader( input_dir="./data", file_extractor={ ".pdf": PDFReader(), ".docx": DocxReader(), }, filename_as_id=True, # 用文件名作为文档 ID，方便溯源 ) docs = reader.load_data() # 手动注入元数据（对后续过滤很重要） for doc in docs: doc.metadata.update({ "category": "技术文档", "author": "工程团队", "version": "v2.0", })6.2 网页数据加载from llama_index.readers.web import SimpleWebPageReader, BeautifulSoupWebPageReader # 简单网页读取（转为纯文本） urls = [ "https://qwen.readthedocs.io/en/latest/", "https://help.aliyun.com/document_detail/xxx.html" ] docs = SimpleWebPageReader(html_to_text=True).load_data(urls) # 进阶：用 BeautifulSoup 保留结构信息 from bs4 import BeautifulSoup import requests def custom_scraper(url): response = requests.get(url, timeout=30) soup = BeautifulSoup(response.text, 'html.parser') # 提取正文，过滤导航栏等噪音 main_content = soup.find('main') or soup.find('article') or soup.find('body') return main_content.get_text(separator='\n', strip=True) if main_content else ""6.3 数据库 / API 加载from llama_index.core import Document import json # 从数据库加载（示例：MySQL） # import pymysql # conn = pymysql.connect(...) # cursor = conn.cursor() # cursor.execute("SELECT title, content FROM knowledge_base") # rows = cursor.fetchall() # docs = [Document(text=row[1], metadata={"title": row[0]}) for row in rows] # 从 JSON/CSV 加载 import pandas as pd df = pd.read_csv("faq.csv") docs = [ Document( text=f"问题: {row['question']}\n答案: {row['answer']}", metadata={"source": "FAQ", "category": row['category']} ) for _, row in df.iterrows() ]7. 索引构建与向量存储7.1 内存索引（开发调试）from llama_index.core import VectorStoreIndex # 默认使用内存中的 SimpleVectorStore，重启后丢失 index = VectorStoreIndex.from_documents(documents)7.2 持久化到本地磁盘from llama_index.core import StorageContext # 保存（会生成 ./storage 目录，包含 docstore、index_store、vector_store） index.storage_context.persist(persist_dir="./storage") # 加载 from llama_index.core import load_index_from_storage storage_context = StorageContext.from_defaults(persist_dir="./storage") index = load_index_from_storage(storage_context)7.3 生产级向量数据库：ChromaDBimport chromadb from llama_index.vector_stores.chroma import ChromaVectorStore from llama_index.core import StorageContext, VectorStoreIndex # 创建 Chroma 客户端 chroma_client = chromadb.PersistentClient(path="./chroma_db") chroma_collection = chroma_client.get_or_create_collection("knowledge_base") # 包装为 LlamaIndex 的 VectorStore vector_store = ChromaVectorStore(chroma_collection=chroma_collection) storage_context = StorageContext.from_defaults(vector_store=vector_store) # 构建索引（数据存入 ChromaDB） index = VectorStoreIndex.from_documents( documents, storage_context=storage_context, show_progress=True ) # 后续加载无需重新 Embedding index = VectorStoreIndex.from_vector_store( vector_store=vector_store, storage_context=storage_context )7.4 生产级向量数据库：Qdrant（推荐）from llama_index.vector_stores.qdrant import QdrantVectorStore import qdrant_client client = qdrant_client.QdrantClient(path="./qdrant_data") # 本地模式 # client = qdrant_client.QdrantClient(host="localhost", port=6333) # 服务端模式 vector_store = QdrantVectorStore( client=client, collection_name="rag_collection", dimension=1024, # 必须与 Embedding 模型维度一致（bge-m3 是 1024） ) storage_context = StorageContext.from_defaults(vector_store=vector_store) index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)8. 检索策略与查询引擎8.1 基础相似度检索query_engine = index.as_query_engine( similarity_top_k=5, # 召回数量 response_mode="compact", # 合成策略 streaming=False, # 是否流式输出 )8.2 带过滤条件的检索（元数据过滤）from llama_index.core.vector_stores import MetadataFilters, ExactMatchFilter # 只检索 category="技术文档" 的内容 filters = MetadataFilters( filters=[ExactMatchFilter(key="category", value="技术文档")] ) query_engine = index.as_query_engine( similarity_top_k=5, filters=filters # 传入过滤条件 )8.3 自定义检索器 + Rerank（高级 RAG 必备）from llama_index.core.retrievers import VectorIndexRetriever from llama_index.core.postprocessor import SentenceTransformerRerank from llama_index.core.query_engine import RetrieverQueryEngine # 1. 宽召回：先取 Top-20 retriever = VectorIndexRetriever( index=index, similarity_top_k=20, ) # 2. 精排序：用 Cross-Encoder Reranker 筛选 Top-5 reranker = SentenceTransformerRerank( model="BAAI/bge-reranker-v2-m3", # 中文 Reranker top_n=5, ) # 3. 组装自定义 Query Engine query_engine = RetrieverQueryEngine.from_args( retriever=retriever, node_postprocessors=[reranker], response_mode="compact", ) # Reranker 能显著提升检索精度（通常 +10~25%）8.4 混合检索：向量 + 关键词from llama_index.core.retrievers import QueryFusionRetriever from llama_index.retrievers.bm25 import BM25Retriever # 创建两种检索器 vector_retriever = index.as_retriever(similarity_top_k=10) bm25_retriever = BM25Retriever.from_defaults(index=index, similarity_top_k=10) # 融合检索（RRF 算法） retriever = QueryFusionRetriever( [vector_retriever, bm25_retriever], similarity_top_k=5, num_queries=1, # 是否开启查询扩展（1=不扩展） mode="reciprocal_rerank", # RRF 融合算法 ) query_engine = index.as_query_engine(retriever=retriever)8.5 流式输出（提升用户体验）query_engine = index.as_query_engine(streaming=True) streaming_response = query_engine.query("解释 RAG 的工作原理") # 逐字输出（类似 ChatGPT 的打字效果） for token in streaming_response.response_gen: print(token, end="", flush=True)9. 高级 RAG 技巧9.1 自动合并检索器（Auto-Merging）解决"切片边界断裂"问题：当检索到的多个片段属于同一父文档时，自动合并为更大的上下文。from llama_index.core.node_parser import HierarchicalNodeParser from llama_index.core.retrievers import AutoMergingRetriever from llama_index.core.storage.docstore import SimpleDocumentStore # 1. 构建层级结构：大切片包含小切片 node_parser = HierarchicalNodeParser.from_defaults( chunk_sizes=[2048, 512], # 第一层 2048，第二层 512 ) nodes = node_parser.get_nodes_from_documents(documents) # 2. 存储到 docstore docstore = SimpleDocumentStore() docstore.add_documents(nodes) # 3. 只用叶子节点（512）构建向量索引 leaf_nodes = [n for n in nodes if n.relationships.get("child") is None] index = VectorStoreIndex(leaf_nodes) # 4. 自动合并检索器 retriever = AutoMergingRetriever( index.as_retriever(similarity_top_k=10), docstore=docstore, verbose=True, ) query_engine = RetrieverQueryEngine.from_args(retriever)9.2 多文档 Agent（路由 + 工具调用）当知识库包含多种类型文档（API 文档、教程、FAQ）时，让 Agent 自动选择数据源：from llama_index.core.tools import QueryEngineTool, ToolMetadata from llama_index.core.agent import ReActAgent # 为每种文档创建独立的 Query Engine api_index = VectorStoreIndex.from_documents(api_docs) tutorial_index = VectorStoreIndex.from_documents(tutorial_docs) api_tool = QueryEngineTool( query_engine=api_index.as_query_engine(), metadata=ToolMetadata( name="api_docs", description="提供 API 接口的详细参数、返回值和错误码信息。", ), ) tutorial_tool = QueryEngineTool( query_engine=tutorial_index.as_query_engine(), metadata=ToolMetadata( name="tutorials", description="提供面向新手的教程和最佳实践指南。", ), ) # 创建 ReAct Agent（千问支持 function calling 时可用） agent = ReActAgent.from_tools( [api_tool, tutorial_tool], llm=Settings.llm, verbose=True, system_prompt="你是技术文档助手。根据用户问题选择最合适的工具查询文档。", ) response = agent.chat("如何调用用户认证接口？")9.3 查询转换（Query Transformation）将复杂问题拆解为多个子问题，分别检索后综合答案：from llama_index.core.indices.query.query_transform import HyDEQueryTransform from llama_index.core.query_engine import TransformQueryEngine # HyDE（假设文档嵌入）：生成假答案后再检索，提升召回率 hyde_transform = HyDEQueryTransform(include_original=True) hyde_query_engine = TransformQueryEngine(query_engine, hyde_transform) response = hyde_query_engine.query("千问模型有哪些优势？")10. 生产化部署要点10.1 性能优化清单优化项开发环境生产环境Embedding 模型CPU / GPUGPU 或专用 Embedding 服务向量存储内存 / 本地文件Qdrant / Milvus / Weaviate索引持久化persist()向量数据库原生持久化并发处理单线程异步 aquery() + 连接池文本切片固定长度SemanticSplitter（语义切片）检索策略Top-K 相似度Hybrid + Rerank10.2 异步 API（FastAPI 集成示例）from fastapi import FastAPI from llama_index.core import Settings import asyncio app = FastAPI() # 全局初始化索引（启动时加载） index = None @app.on_event("startup") async def load_index(): global index storage_context = StorageContext.from_defaults(persist_dir="./storage") index = load_index_from_storage(storage_context) @app.post("/query") async def query(question: str): query_engine = index.as_query_engine() # 使用异步接口避免阻塞事件循环 response = await query_engine.aquery(question) return { "answer": str(response), "sources": [ {"file": n.metadata.get("file_name"), "score": n.score} for n in response.source_nodes ] }10.3 监控与评估from llama_index.core.callbacks import CallbackManager, LlamaDebugHandler import time # 添加调试处理器，追踪每一步耗时 debug_handler = LlamaDebugHandler(print_trace_on_end=True) Settings.callback_manager = CallbackManager([debug_handler]) # 执行查询后会自动打印： # - 检索耗时 # - LLM 调用耗时 # - Token 使用量 response = query_engine.query("测试问题")11. 完整可运行代码汇总11.1 最小可用示例（DashScope API + 本地文件）""" 最小可用 RAG 系统 依赖: pip install llama-index llama-index-llms-openai-like llama-index-embeddings-dashscope """ import os from llama_index.core import ( VectorStoreIndex, SimpleDirectoryReader, Settings, StorageContext, load_index_from_storage ) from llama_index.llms.openai_like import OpenAILike from llama_index.embeddings.dashscope import DashScopeEmbedding # ========== 配置 ========== Settings.llm = OpenAILike( model="qwen-turbo", api_base="https://dashscope.aliyuncs.com/compatible-mode/v1", api_key=os.getenv("DASHSCOPE_API_KEY"), context_window=8192, is_chat_model=True, ) Settings.embed_model = DashScopeEmbedding( model_name="text-embedding-v2", api_key=os.getenv("DASHSCOPE_API_KEY") ) # ========== 构建索引 ========== if os.path.exists("./storage"): storage_context = StorageContext.from_defaults(persist_dir="./storage") index = load_index_from_storage(storage_context) else: documents = SimpleDirectoryReader("./data").load_data() index = VectorStoreIndex.from_documents(documents) index.storage_context.persist("./storage") # ========== 查询 ========== query_engine = index.as_query_engine(similarity_top_k=5) response = query_engine.query("介绍千问模型的特点") print(response)11.2 完整生产级示例（本地 Qwen + ChromaDB + Rerank）""" 生产级 RAG 系统 依赖: pip install llama-index llama-index-llms-huggingface llama-index-embeddings-huggingface pip install llama-index-vector-stores-chroma chromadb pip install transformers torch sentence-transformers """ import os import torch from llama_index.core import ( Settings, VectorStoreIndex, SimpleDirectoryReader, StorageContext, load_index_from_storage, PromptTemplate ) from llama_index.llms.huggingface import HuggingFaceLLM from llama_index.embeddings.huggingface import HuggingFaceEmbedding from llama_index.vector_stores.chroma import ChromaVectorStore from llama_index.core.node_parser import SentenceSplitter from llama_index.core.retrievers import VectorIndexRetriever from llama_index.core.postprocessor import SentenceTransformerRerank from llama_index.core.query_engine import RetrieverQueryEngine import chromadb # ========== 1. 千问提示词模板 ========== def messages_to_prompt(messages): prompt = "" for message in messages: if message.role == "system": prompt += f"<|im_start|>system\n{message.content}e<|im_end|>\n" elif message.role == "user": prompt += f"<|im_start|>user\n{message.content}e<|im_end|>\n" elif message.role == "assistant": prompt += f"<|im_start|>assistant\n{message.content}e<|im_end|>\n" if not prompt.startswith("<|im_start|>system"): prompt = "<|im_start|>system\nYou are Qwen, created by Alibaba Cloud. You are a helpful assistant.e<|im_end|>\n" + prompt prompt += "<|im_start|>assistant\n" return prompt # ========== 2. 全局配置 ========== Settings.llm = HuggingFaceLLM( model_name="Qwen/Qwen2.5-7B-Instruct", tokenizer_name="Qwen/Qwen2.5-7B-Instruct", context_window=32768, max_new_tokens=2048, generate_kwargs={"temperature": 0.7, "top_p": 0.95, "do_sample": True}, messages_to_prompt=messages_to_prompt, device_map="auto", model_kwargs={"torch_dtype": torch.float16}, ) Settings.embed_model = HuggingFaceEmbedding( model_name="BAAI/bge-m3", device="cuda", trust_remote_code=True, ) Settings.transformations = [SentenceSplitter(chunk_size=1024, chunk_overlap=200)] # ========== 3. ChromaDB 向量存储 ========== chroma_client = chromadb.PersistentClient(path="./chroma_db") chroma_collection = chroma_client.get_or_create_collection("rag_prod") vector_store = ChromaVectorStore(chroma_collection=chroma_collection) storage_context = StorageContext.from_defaults(vector_store=vector_store) # ========== 4. 加载或构建索引 ========== if os.path.exists("./chroma_db") and chroma_collection.count() > 0: index = VectorStoreIndex.from_vector_store(vector_store=vector_store) else: documents = SimpleDirectoryReader("./data").load_data() index = VectorStoreIndex.from_documents(documents, storage_context=storage_context) # ========== 5. 高级检索：宽召回 + Rerank ========== retriever = VectorIndexRetriever(index=index, similarity_top_k=20) reranker = SentenceTransformerRerank(model="BAAI/bge-reranker-v2-m3", top_n=5) query_engine = RetrieverQueryEngine.from_args( retriever=retriever, node_postprocessors=[reranker], response_mode="compact", ) # ========== 6. 执行查询 ========== response = query_engine.query("千问模型在中文理解方面有哪些优势？") print("\n=== 回答 ===") print(response) print("\n=== 引用来源 ===") for node in response.source_nodes: print(f"[{node.score:.4f}] {node.metadata.get('file_name', 'unknown')}: {node.text[:120]}...")附录：常见问题排查Q1: ImportError: cannot import name 'ServiceContext' from 'llama_index'原因: 你正在使用 0.10+ 版本，但代码是 0.9.x 的老写法。 解决: 用 Settings 替代 ServiceContext：# 旧写法（已废弃） from llama_index import ServiceContext service_context = ServiceContext.from_defaults(...) # 新写法 from llama_index.core import Settings Settings.llm = ... Settings.embed_model = ...Q2: 千问模型输出乱码 / 重复特殊 token原因: 未正确配置 messages_to_prompt 模板，导致 ChatML 格式错误。 解决: 必须严格使用官方模板（见第 5 节方式 B），确保 <|im_start|> 和 <|im_end|> 标签完整。Q3: Embedding 阶段 CUDA Out of Memory解决:Settings.embed_model = HuggingFaceEmbedding( model_name="BAAI/bge-m3", device="cpu", # 改为 CPU 运行 Embedding（CPU 足够快） # 或减小 batch size embed_batch_size=1, )Q4: 中文检索效果差解决:使用中文优化 Embedding：BAAI/bge-m3 或 BAAI/bge-large-zh-v1.5使用中文 Reranker：BAAI/bge-reranker-v2-m3调整切片大小：中文文档建议 chunk_size=512~1024（中文字符密度高）增加 overlap：chunk_overlap=100~200Q5: 如何升级 LlamaIndex？pip install --upgrade llama-index pip install --upgrade llama-index-core # 然后逐一升级子包 pip install --upgrade llama-index-llms-huggingface pip install --upgrade llama-index-embeddings-huggingface文档版本: v1.0 适配版本: llama-index-core >= 0.14.0, Qwen2.5/3 最后验证: 2026-05-13
介绍多消息模板（系统 + 人类）适配对话场景，分离系统指令和人类问题，更符合大模型的对话习惯：codeimport os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, SystemMessage from langchain_core.prompts import ChatPromptTemplate # 加载环境变量 load_dotenv() # 获取密钥 # 定义配置字典 (注意使用冒号 :) qwen_config = { "api_key": os.getenv("QWEN_API_KEY"), # 获取QWEN_API_KEY "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", # 请求地址 "model_name": "qwen3.5-flash", } model_config = qwen_config # 初始化聊天模型 chat_model = ChatOpenAI( model=model_config["model_name"], # 模型名称 api_key=model_config["api_key"], base_url=model_config["base_url"], temperature=0.7, # 生成随机性，0-1，0为最严谨，1为最灵活 ) # 定义多消息模板，分别设置system和human的内容，{question}为人类问题变量 chat_prompt = ChatPromptTemplate.from_messages( [ ("system", "你是一个数学解题助手，只给出解题步骤和答案，不做额外解释"), ("human", "请解决这个数学题：{question}"), ] ) # 2. # 传入变量生成消息 messages = chat_prompt.invoke({"question": "2x+5=15，求x的值"}) chain = chat_prompt | chat_model # LangChain 1.0的管道符语法，简洁高效 # 调用模型生成结果 response = chain.invoke(messages) # 输出结果 print(response.content)
介绍Prompt Template（提示词模板）组件 核心作用：解决提示词硬编码的问题，实现提示词的模板化、参数化，提升复用性，支持动态传入变量，适配不同问题场景。Codeimport os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, SystemMessage from langchain_core.prompts import ChatPromptTemplate # Prompt Template（提示词模板）组件 # 核心作用：解决提示词硬编码的问题，实现提示词的模板化、参数化，提升复用性，支持动态传入变量，适配不同问题场景。 # 加载环境变量 load_dotenv() # 获取密钥 # 定义配置字典 (注意使用冒号 :) qwen_config = { "api_key": os.getenv("QWEN_API_KEY"), # 获取QWEN_API_KEY "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", # 请求地址 "model_name": "qwen3.5-flash", } model_config = qwen_config # 初始化聊天模型 chat_model = ChatOpenAI( model=model_config["model_name"], # 模型名称 api_key=model_config["api_key"], base_url=model_config["base_url"], temperature=0.7, # 生成随机性，0-1，0为最严谨，1为最灵活 ) template = """ 你是一个专业的科普博主，用通俗易懂的语言讲解{topic}，回答控制在100字以内。 """ # 初始化聊天提示词模板 prompt = ChatPromptTemplate.from_template(template) # 2. 向模板传入变量，生成标准化的聊天消息 messages = prompt.invoke({"topic": "大语言模型的嵌入技术"}) chain = prompt | chat_model # LangChain 1.0的管道符语法，简洁高效 # 调用模型生成结果 response = chain.invoke(messages) # 输出结果 print(response.content)
import os from dotenv import load_dotenv from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, SystemMessage # 对接各类聊天大模型，实现对话式文本生成，是 LangChain 1.0 最常用的模型组件，替代了旧版本的部分 LLM 使用场景。 # 加载环境变量 load_dotenv() # 获取密钥 # 定义配置字典 (注意使用冒号 :) qwen_config = { "api_key": os.getenv("QWEN_API_KEY"), # 获取QWEN_API_KEY "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1", # 请求地址 "model_name": "qwen3.5-flash", } zhipu_config = { "api_key": os.getenv("ZHIPU_API_KEY"), # ZHIPU_API_KEY "base_url": "https://open.bigmodel.cn/api/paas/v4", # 请求地址 "model_name": "glm-4.5", } baidu_config = { "api_key": os.getenv("BAIDU_API_KEY"), # BAIDU_API_KEY "base_url": "https://qianfan.baidubce.com/v2", # 请求地址 "model_name": "deepseek-v3.1-250821", } # print(qwen_config) # breakpoint() model_config = baidu_config # 初始化聊天模型 chat_model = ChatOpenAI( model=model_config["model_name"], # 模型名称 api_key=model_config["api_key"], base_url=model_config["base_url"], temperature=0.7, # 生成随机性，0-1，0为最严谨，1为最灵活 ) # 构造聊天消息：SystemMessage（系统指令）→ HumanMessage（人类问题） messages = [ SystemMessage(content="你是一个友好的Python编程助手，回答简洁易懂"), HumanMessage(content="请介绍一下你自己"), ] # 调用模型生成结果 response = chat_model.invoke(messages) # 输出结果 print(response.content)
国内知名大模型及其API调用平台的官方网址汇总
互联网巨头系厂商模型系列API平台名称官方网址 (控制台/首页)备注阿里巴巴通义千问 (Qwen)阿里云百炼https://bailian.console.aliyun.com集成通义全系列及开源模型，新用户送高额Tokens百度文心一言 (ERNIE)百度智能云千帆https://console.bce.baidu.com/qianfan需登录百度智能云控制台，支持多种文心模型腾讯混元 (Hunyuan)腾讯云混元大模型https://cloud.tencent.com/product/hunyuan在腾讯云控制台内选择“混元”服务华为盘古 (Pangu)华为云 ModelArtshttps://www.huaweicloud.com/product/modelarts.html侧重行业模型，需进入ModelArts控制台管理科大讯飞星火 (Spark)讯飞开放平台https://www.xfyun.cn语音类API入口，大模型在“认知大模型”板块垂直领域独角兽厂商模型系列API平台名称官方网址 (控制台/首页)备注月之暗面Kimi (Moonshot)月之暗面开放平台https://platform.moonshot.cn长文本处理首选，界面简洁深度求索DeepSeekDeepSeek开放平台https://platform.deepseek.com高性价比，代码与推理能力强智谱AIGLM (智谱清言)智谱开放平台 (BigModel)https://open.bigmodel.cn提供GLM-4等系列，Agent开发友好MiniMaxABABMiniMax开放平台https://api.minimax.chat角色扮演与语音合成见长商汤科技日日新 (SenseNova)商汤SenseCloudhttps://www.sensecore.com.cn多模态与视觉能力突出零一万物Yi (万悟)零一万物开放平台https://platform.lingyiwanwu.com开源模型商业化代表之一聚合与中转平台 (可选)平台名称官方网址特点硅基流动 (SiliconFlow)https://siliconflow.cn提供多家主流模型的高速推理API，兼容OpenAI格式火山引擎 (方舟)https://www.volcengine.com字节系模型及第三方模型聚合，控制台选“方舟”OneAPI (开源项目)https://github.com/songquanpeng/one-api可自建的中转系统，统一管理多个上游渠道
vLLM运行模型显存不足的原因及解决方法在使用vLLM部署大语言模型时，显存不足是最常见的报错（如提示“Free memory on device cuda:0 is less than desired GPU memory utilization”），其核心是GPU显存无法满足模型运行、优化策略及任务负载的综合需求。以下将详细分析显存不足的原因，并提供按优先级排序的可操作解决方法，适配各类常见场景（尤其针对8GB等小显存设备）。一、显存不足的核心原因vLLM显存占用主要分为「模型本身占用」「vLLM优化策略占用」「任务负载占用」三类，任一环节超出GPU显存上限，都会导致启动或运行失败，具体原因如下：1. 模型本身占用超出显存上限（最常见）这是最核心的原因，模型的参数规模、精度直接决定基础显存占用：参数规模过大：如13B、34B级别的模型，原生FP16精度下，单卡（如8GB显存）无法容纳（13B模型FP16精度约占用26GB显存），即使是7B模型，原生精度也需约14GB显存，8GB显存设备直接超出上限。模型精度过高：vLLM默认使用FP16精度运行模型，相比FP32精度虽已减半显存占用，但对小显存设备（8GB及以下）仍不友好；若未开启量化，原生精度的显存占用会直接超出设备承载能力。2. vLLM优化策略的显存预留过高vLLM为提升推理速度，会默认预留一定比例的显存用于优化（如CUDA图、PagedAttention分页机制），其中最关键的是「GPU显存利用率」参数：默认显存利用率过高：vLLM默认gpu_memory_utilization=0.85，即会尝试占用GPU 85%的显存用于模型加载和优化。例如8GB显存设备，默认需要占用约6.8GB显存，若设备本身可用显存不足（如被其他进程占用后剩余6.7GB），就会直接报错。CUDA图优化的显存预留：vLLM默认启用CUDA图优化，会额外预留部分显存用于加速推理，对于8GB等小显存设备，这部分预留会进一步挤压模型可用显存。3. 任务负载及环境干扰除模型和优化策略外，外部环境和任务设置也会占用显存，导致可用显存不足：其他进程占用显存：GPU上同时运行其他程序（如Jupyter内核、其他Python进程、PyTorch缓存），会占用部分显存，导致vLLM可使用的显存减少（如你之前的报错中，8GB显存仅剩余6.7GB可用）。任务参数设置不合理：如单批次token数（max-num-batched-tokens）设置过高、并发请求过多，会导致推理过程中显存占用临时飙升，超出预留显存。分布式配置错误：若误设置tensor-parallel-size（张量并行数）大于1，单卡会尝试加载部分模型参数+通信开销，额外增加显存占用，单卡部署时此参数必须为1。4. 次要原因：环境配置或版本冲突vLLM与PyTorch、CUDA版本不兼容，或未清理显存缓存，会导致显存泄露、占用异常，间接引发显存不足（如你之前遇到的NCCL进程组未销毁警告，虽不直接导致显存不足，但会造成显存泄露，长期运行会加剧问题）。二、显存不足的解决方法（按优先级从易到难）解决思路：先快速释放可用显存、降低显存预留，再通过量化、调整参数进一步优化，最后排查环境和模型问题，确保每一步都可落地、见效快。1. 快速释放显存（立即见效，优先操作）针对“其他进程占用显存”“显存缓存”问题，快速释放可用显存，无需修改模型或配置：关闭占用GPU的其他进程查看GPU进程：执行命令 nvidia-smi，查看占用GPU的进程ID（PID）。杀死进程：执行命令 kill -9 <PID>（替换<PID>为实际进程号，如Jupyter、多余Python进程）。清理PyTorch显存缓存：若之前运行过PyTorch程序，执行以下代码清理缓存（可在启动vLLM前运行）：`import torchtorch.cuda.empty_cache() # 清理未使用的显存缓存torch.cuda.reset_max_memory_allocated() # 重置显存统计`重启GPU相关服务：若显存泄露严重，可重启电脑或GPU驱动（执行 nvidia-smi -r，部分系统需sudo权限）。2. 降低vLLM显存预留（适配小显存设备，核心操作）针对“显存利用率过高”“CUDA图预留”问题，修改vLLM启动参数，直接减少显存占用，适配8GB等小显存设备：降低GPU显存利用率（最关键）启动vLLM时，通过 --gpu-memory-utilization 参数降低显存占用比例，建议8GB显存设备设置为0.7~0.8（根据可用显存调整）。示例启动命令（OpenAI兼容服务器）：`python -m vllm.entrypoints.openai.api_server \ --model 你的模型名 \--gpu-memory-utilization 0.75 # 8GB显存推荐0.7~0.8，减少预留显存 --tensor-parallel-size 1 # 单卡必须设为1，避免额外显存开销`禁用CUDA图优化 vLLM默认启用CUDA图加速推理，会预留部分显存，禁用后可释放约500MB~1GB显存，适合小显存设备：`python -m vllm.entrypoints.openai.api_server \--model 你的模型名 \--gpu-memory-utilization 0.75 \ --disable-cuda-graphs # 禁用CUDA图，减少显存预留 --enforce-eager # 可选：强制即时执行，进一步降低显存占用（牺牲少量速度）`3. 量化模型（大幅减少显存占用，进阶操作）若降低显存预留后仍不足，通过模型量化将显存占用减少50%~75%，是小显存设备运行大模型的核心方案，vLLM支持AWQ、GPTQ、SqueezeLLM等量化格式：使用量化模型（推荐） 直接下载已量化的模型（如Hugging Face上的AWQ/GPTQ量化版模型，标注“4-bit”“8-bit”），启动时指定量化格式即可：`# 8-bit AWQ量化（兼容性好，显存占用减少约50%）-m vllm.entrypoints.openai.api_server \--model 模型名（如TheBloke/Llama-2-7B-Chat-AWQ） \ --gpu-memory-utilization 0.75 \ --quantization awq \ --tensor-parallel-size 1`注意：量化格式需与模型匹配（AWQ模型对应--quantization awq，GPTQ模型对应--quantization gptq）。原生模型量化（若没有量化版模型） 若只有原生模型，可使用vLLM自带的量化工具，或借助第三方工具（如auto-gptq）先量化模型，再启动vLLM（步骤略复杂，适合有一定技术基础的用户）。 4. 调整任务参数（减少运行时显存波动）即使模型加载成功，运行时若任务参数设置不合理，也会出现显存飙升、报错的情况，需调整以下参数：降低单批次token数：通过 --max-num-batched-tokens 限制单批次处理的token总数，减少推理时的显存占用（8GB显存推荐设为512~1024）： `--max-num-batched-tokens 512` 限制并发请求数：若通过API部署，可通过 --max-num-seqs 限制同时处理的请求数，避免并发过高导致显存叠加： `--max-num-seqs 4 # 8GB显存推荐1~4，根据请求复杂度调整` 缩短生成token长度：在调用模型时，限制 max_tokens（生成的最大token数），避免生成过长文本导致显存飙升（如设为128~256）。5. 排查环境与版本（解决隐性显存问题）若以上方法均无效，需排查环境配置，避免版本冲突或显存泄露：适配vLLM、PyTorch、CUDA版本：vLLM对版本要求较高，推荐组合：CUDA：11.8+（推荐12.1，兼容性最好）PyTorch：2.0+vLLM：0.4.0+（最新版本修复了部分显存泄露问题）解决NCCL进程组警告：若出现“destroy_process_group() was not called”警告，需在自定义代码中添加进程销毁逻辑，避免显存泄露：`import torch.distributed as dist 在代码结束前添加（仅当使用分布式部署时）if dist.is_initialized():dist.destroy_process_group()`注：若为单卡部署，此警告多为模型启动失败导致，解决显存问题后会自动消失。 6. 终极方案：更换模型或硬件若以上方法均无法解决，说明当前硬件或模型不匹配，可选择：更换更小的模型：如8GB显存设备，优先选择7B量化版模型（4-bit量化后仅需3~4GB显存），避免使用13B及以上规模模型。升级GPU硬件：若需运行更大模型（如13B、34B），建议更换16GB及以上显存的GPU（如RTX 3090、RTX 4090）。三、常见场景适配示例（直接套用）场景1：8GB显存，运行7B原生模型（报错“显存不足”）# 推荐启动命令（降低显存利用率+禁用CUDA图） python -m vllm.entrypoints.openai.api_server \ --model 你的7B原生模型名 \ --gpu-memory-utilization 0.75 \ --disable-cuda-graphs \ --enforce-eager \ --tensor-parallel-size 1 \ --max-num-batched-tokens 512场景2：8GB显存，运行7B AWQ量化模型（仍报错）# 推荐启动命令（进一步降低显存利用率+限制并发） python -m vllm.entrypoints.openai.api_server \ --model TheBloke/Llama-2-7B-Chat-AWQ \ --gpu-memory-utilization 0.7 \ --quantization awq \ --tensor-parallel-size 1 \ --max-num-batched-tokens 512 \ --max-num-seqs 2四、注意事项优先级：先释放显存、降低显存利用率，再尝试量化，最后调整任务参数，避免盲目操作。权衡速度与显存：降低显存利用率、禁用CUDA图、量化模型，都会牺牲少量推理速度，需根据需求平衡（如追求速度可适当提高显存利用率，追求稳定性则降低）。模型兼容性：量化模型需与vLLM支持的量化格式匹配，否则会报错；部分小众模型可能不支持量化，需更换模型。总结：vLLM显存不足的核心是“显存需求＞设备可用显存”，解决的关键的是“减少显存需求”（降低预留、量化模型、调整参数）和“增加可用显存”（清理进程、清理缓存），结合实际硬件和模型选择对应方法，即可快速解决问题。（注：文档部分内容可能由 AI 生成）
Hugging Face 下载vLLm使用的模型前往Hugging Face 寻找自己需要的模型例如：下载这个模型 https://huggingface.co/Qwen/Qwen3-VL-4B-Instruct复制模型名称 Qwen/Qwen3-VL-4B-Instruct下载模型使用 huggingface-cli 命令行工具（推荐）pip install huggingface_hub登录 Hugging Face（如果是私有模型或需要避免速率限制）公共模型可以不用huggingface-cli login然后输入你的 Access Token (https://huggingface.co/settings/tokens)下载模型：export HF_ENDPOINT=https://hf-mirror.comhf download Qwen/Qwen3-VL-4B-Instruct --local-dir Qwen3-VL-4B普通版本的模型会默认占用90%的显存，可能会出现显存不够的问题，可以选择量化版本的模型进行下载mac 安装vllm 下载模型流程#创建虚拟环境 conda create --name vllm_dev python=3.12 #使用环境 conda activate vllm_dev #安装huggingface_hub pip install huggingface_hub #下载模型 export HF_ENDPOINT=https://hf-mirror.com hf download Qwen/Qwen3-Embedding-0.6B