大模型从“能聊天”到“能干活”中间其实还隔着好几个关键环节。很多人把模型部署起来之后发现回答质量不稳定、知识过期、不会调用工具、稍微复杂一点的任务就卡住于是开始怀疑是不是模型本身不行。实际上多数情况下不是模型能力不够而是你把 Prompt、微调、RAG、Agent 这几层工程手段的边界搞混了。本文围绕 Qwen3.5 这条主线完整梳理大模型从部署、Prompt 调优、LoRA/QAT 微调到 RAG 知识库和 ReAct Agent 的落地链路。内容偏实战代码尽量完整可复制也会把高频报错和排查思路单独列出来。无论你是刚开始接触大模型的新手还是已经做过简单 API 调用的开发者都能从里面找到可以直接用的方案。1. 背景为什么大模型落地还需要“四件套”1.1 大模型应用的基本路径先看一张简化的大模型落地链路业务需求 - Prompt 工程 - 模型调用 - RAG 知识增强 - Agent 工具调用 - 微调 / 量化 - 部署上线这层结构解释了为什么现在大模型相关的技术词汇如此密集不是每个问题都需要微调也不是所有场景都必须上 Agent。你需要先判断当前业务的核心瓶颈在哪一层。如果模型回答风格不对、不理解业务术语优先考虑 Prompt 优化。如果模型知识不足、需要回答私有文档中的内容优先考虑 RAG。如果模型需要调用多个外部系统、完成多步推理任务优先考虑 Agent ReAct。如果 Prompt 无论如何调都效果有限且你有一定量高质量业务数据再考虑微调。如果要部署到低资源环境还要考虑量化GGUF、GPTQ、QAT 等。1.2 四件套分别解决什么问题Prompt最轻量、成本最低的模型控制方式。它不改变模型参数只改变模型的输入指令用于约束输出格式、推理步骤、回答风格。ReAct推理与行动交替执行的模式。模型先“思考”需要做什么再“行动”调用工具最后根据工具返回结果继续推理。RAG检索增强生成。先从外部知识库检索相关内容再拼入 Prompt 让模型生成答案解决知识实时性和私有知识问题。Agent以模型为大脑自主拆解任务、调用工具、完成复杂工作流的系统。QATQuantization-Aware Training量化感知训练。在训练阶段就模拟量化误差让量化后的模型损失更小是部署优化的关键手段之一。Harness通常指模型评测框架或 Agent 运行时的“控制台”。它负责加载模型、执行评测任务、记录推理过程是工程化落地中容易被忽略但很重要的一层。1.3 关于 Qwen3.5 的版本说明本文以 Qwen3.5 为线索主要是因为它是当前中文开源大模型中生态比较完整的一支官方仓库同时提供了基础模型、对话模型、GGUF 量化版本并且对 llama.cpp、Ollama、Transformers、vLLM 都支持得比较成熟。需要注意大模型版本迭代很快本文出现的模型名、命令、参数请以你本地实际的模型仓库为准。核心方法论是通用的换成其他 Qwen 系列模型也能跑通。2. 环境准备与版本选择2.1 硬件环境微调和推理对硬件的要求差异很大。下面给出一个参考区间场景最低要求建议配置纯 Prompt API 调用无特殊要求普通开发机即可本地推理 7B/9B 模型16GB 内存24GB 内存 8GB 显存本地推理 13B/14B 模型24GB 内存32GB 内存 12GB 以上显存LoRA 微调 7B/9B16GB 显存24GB 以上显存QAT 全参量化训练32GB 显存多卡环境如果你的机器达不到微调要求也可以先用 API 或云端 GPU 完成实验本地只跑推理。2.2 软件环境本文示例以 Linux 环境为主Windows 下需要使用 WSL2 或调整部分命令。核心软件版本如下Python 3.10 或 3.11CUDA 11.8 或 12.1根据显卡驱动选择PyTorch 2.xTransformers 4.40PEFT 0.7llama.cpp最新 releaseOllama最新 releaseFastAPI、uvicorn、faiss-cpu、sentence-transformers版本不要求完全一致但要注意PyTorch 和 CUDA 版本必须匹配否则会在导入 torch 时直接报错。2.3 推荐工具链清单用一张表把本文会用到的工具串起来工具作用Ollama最省事的模型加载和推理入口llama.cpp本地 GGUF 推理CPU 也能跑Transformers PEFTLoRA 微调、加载模型sentence-transformers文本向量化FAISS向量检索FastAPI封装 HTTP 接口LM Harness模型评测和 Agent 运行控制3. 先学会提问如何编写并调优 Prompt3.1 一个 Prompt 的基本结构不要把 Prompt 理解成“给模型写一句话”。一个结构完整的 Prompt 通常包含以下部分角色告诉模型它是什么身份。任务明确要做什么。上下文提供背景资料或数据。约束限制输出格式、长度、禁止事项。示例给出 1 到 2 个输入输出范例。以 Qwen3.5 为例一个结构完整的系统提示词可以这样写你是一名资深客服质检员。请根据给定的用户与客服对话记录判断客服是否存在以下问题态度不友好、回复敷衍、未解决问题。输出格式为 JSON字段包括 problem、level、reason。只输出 JSON不要解释。这种写法比“帮我分析对话”要稳定得多。原因是模型在解码时根据 Token 概率生成内容约束越明确候选输出空间越小越不容易跑偏。3.2 系统性提示词框架在真实项目中我建议把提示词拆成可维护的模板而不是每次硬编码。下面是一个简单示例system_prompt 你是一个严谨的 {domain} 助手。请遵循以下规则 1. 只基于“已知信息”回答问题不要编造。 2. 如果信息不足请明确回答“资料中未提及”。 3. 回答结构先说结论再补充依据。 4. 最终输出必须控制在 {max_length} 字以内。 这种做法的好处是提示词一旦调好可以在不同接口中复用后续想调整语气或规则时只需要改模板不用改业务代码。3.3 Prompt 调优的常见思路Prompt 调优不是玄学而是有迹可循的迭代过程先跑一个 baseline记录输出质量。分析错误类型是格式错误、知识错误还是推理错误针对错误类型调整对应模块。格式错误就在约束部分加示例知识错误就补充上下文推理错误就把推理步骤拆开要求“一步步思考”。每次只改一个变量避免把所有修改堆在一起后无法定位原因。这里还要区分一个概念Skill 是不是高级版 Prompt从表面看Skill 确实是一组精心编写的提示词工程模板但它往往还包含预设的工具调用规则、输出解析逻辑和错误恢复机制。可以理解为“封装了运行逻辑的 Prompt”而本文后面讲的 Agent 则更强调“循环”和“工具执行”。3.4 关于 invalid prompt 的说明调用模型接口时有时会遇到这类错误invalid prompt: your prompt was flagged as potentially violating our usage policy. please try again with a different prompt.这不是模型坏了而是内容安全过滤器拦截了输入。出现这种提示通常是因为输入文本命中了某些敏感规则。解决思路如下检查业务场景本身是否存在违规风险调整输入内容。避免在输入中堆叠大量负面关键词即使上下文是安全的。如果只是误判可以改用更中性的表述、补充正面的限定词比如“模拟一份合规培训内容”而不是直接罗列敏感词。在本地部署环境下如果你使用的是官方模型该提示通常来自 API 网关而不是模型本身如果确实被拦截需要从网关策略上调整。4. 基于 Ollama 和 llama.cpp 部署 Qwen3.54.1 Ollama 部署流程Ollama 是目前最简单的大模型本地运行工具之一适合快速验证。安装完成后拉取模型并运行# 拉取 Qwen3.5 9B 模型 ollama pull qwen3.5:9b # 直接交互式对话 ollama run qwen3.5:9b # 查看已安装模型 ollama listOllama 还提供了本地 HTTP API。默认端口是 11434可以直接用 curl 调用curl http://localhost:11434/api/chat \ -H Content-Type: application/json \ -d { model: qwen3.5:9b, messages: [ {role: system, content: 你是一个严谨的中文助手。}, {role: user, content: 用一句话解释大模型微调} ], stream: false }如果拉取模型速度慢可以配置国内镜像源。Ollama 支持通过环境变量设置镜像地址具体地址请以你所在网络环境的可用镜像为准。4.2 使用 llama.cpp 部署 GGUF 模型如果你的机器内存有限或者想实现 CPU 推理llama.cpp 是更合适的选择。把 Qwen3.5 转换为 GGUF 格式或直接下载别人量化好的 GGUF 文件后启动 server 模式git clone https://github.com/ggerganov/llama.cpp cd llama.cpp cmake -B build -DCMAKE_BUILD_TYPERelease cmake --build build --config Release -j # 启动服务 ./build/bin/llama-server \ -m /path/to/qwen3.5-9b.gguf \ -c 8192 \ --host 127.0.0.1 \ --port 8080启动完成后可以访问/v1/chat/completions接口这与 OpenAI 接口格式兼容方便后续接 RAG 或 Agent 框架。4.3 基于 FastAPI 封装统一模型服务在项目开发中业务方通常不希望直接面对 Ollama 或 llama.cpp 的接口差异。更规范的做法是增加一层统一网关。下面给出一个最小可用的 FastAPI 封装# 文件路径app/main.py from fastapi import FastAPI from pydantic import BaseModel import requests app FastAPI(titleQwen3.5 Gateway) OLLAMA_URL http://localhost:11434/api/chat MODEL_NAME qwen3.5:9b class ChatRequest(BaseModel): prompt: str system: str 你是一个乐于助人的中文助手。 temperature: float 0.7 class ChatResponse(BaseModel): reply: str app.post(/chat, response_modelChatResponse) def chat(req: ChatRequest): payload { model: MODEL_NAME, messages: [ {role: system, content: req.system}, {role: user, content: req.prompt} ], stream: False, options: { temperature: req.temperature } } resp requests.post(OLLAMA_URL, jsonpayload, timeout120) resp.raise_for_status() data resp.json() return ChatResponse(replydata[message][content])启动命令uvicorn app.main:app --host 0.0.0.0 --port 8000有了这层网关后面接 RAG、Agent 时就可以只对接一个统一接口不需要关心底层是 Ollama 还是 llama.cpp。5. 大模型微调实战以 LoRA / QAT 为例5.1 什么时候需要微调微调的核心目的是“改变模型的行为习惯”而不是“给模型塞知识”。当你发现以下情况时才真正需要微调模型输出风格和你的业务差异太大Prompt 无论怎么写都拉不回来。模型在特定格式任务上表现差比如必须输出严格 JSON 或特定标签。你的业务场景有大量专业术语且 RAG 召回效果有限。你需要模型具备某种固定任务闭环能力比如把口语日志改写成标准工单。如果你只是想让模型回答公司文档里的内容优先做 RAG而不是微调。微调需要数据、算力和更多维护成本但并不会让模型凭空获得新知识。5.2 准备微调数据微调数据通常采用 JSONL 格式每条数据是一个“指令 输出”对。这里给出一个 Qwen 对话格式的训练样本{instruction: 将下面日志改写成标准故障工单连接超时。, output: 【故障现象】客户端连接外部服务时发生超时。\n【影响范围】依赖该服务的业务模块。\n【建议动作】检查网络连通性及对端服务状态。}数据质量比数据数量重要。几十条高质量样本可能比几千条噪声数据效果更好。建议先把数据清洗出来人工抽检 20% 以上确保指令和输出是一一对应的不应该出现“同样的指令不同输出”的情况。5.3 LoRA 微调代码LoRA 是一种参数高效微调方法它只训练一小部分低秩矩阵显存占用明显低于全参微调。下面给出基于 Transformers PEFT 的完整示例# 文件路径train_lora.py import json from datasets import Dataset from transformers import ( AutoModelForCausalLM, AutoTokenizer, TrainingArguments, Trainer ) from peft import LoraConfig, get_peft_model # 1. 读取数据 with open(train_data.jsonl, r, encodingutf-8) as f: raw_data [json.loads(line) for line in f] def build_chat_text(item): return ( |im_start|system\n 你是一个业务知识助手。\n |im_end|\n f|im_start|user\n{item[instruction]}\n|im_end|\n f|im_start|assistant\n{item[output]}\n|im_end| ) dataset Dataset.from_list([{text: build_chat_text(x)} for x in raw_data]) # 2. 加载模型与分词器 model_name Qwen/Qwen3.5-9B tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) model AutoModelForCausalLM.from_pretrained( model_name, torch_dtypeauto, device_mapauto, trust_remote_codeTrue ) # 3. 配置 LoRA lora_config LoraConfig( r16, lora_alpha32, target_modules[ q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj ], lora_dropout0.05, biasnone, task_typeCAUSAL_LM ) model get_peft_model(model, lora_config) model.print_trainable_parameters() # 4. Tokenize def tokenize_function(examples): return tokenizer( examples[text], truncationTrue, max_length2048, paddingFalse ) tokenized_dataset dataset.map( tokenize_function, batchedTrue, remove_columns[text] ) # 5. 训练参数 training_args TrainingArguments( output_dir./qwen3.5-lora-checkpoints, per_device_train_batch_size2, gradient_accumulation_steps8, num_train_epochs3, learning_rate2e-4, logging_steps10, save_steps500, fp16True, report_tonone ) trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_dataset, ) trainer.train() model.save_pretrained(./qwen3.5-lora-final)训练完成后可以用下面的代码合并 LoRA 权重并保存完整模型from peft import PeftModel from transformers import AutoModelForCausalLM, AutoTokenizer base_model AutoModelForCausalLM.from_pretrained( Qwen/Qwen3.5-9B, torch_dtypeauto, device_mapauto ) model PeftModel.from_pretrained( base_model, ./qwen3.5-lora-final ) merged_model model.merge_and_unload() merged_model.save_pretrained(./qwen3.5-merged) tokenizer.save_pretrained(./qwen3.5-merged)5.4 量化感知训练 QAT 简介QAT 的原理是让模型在训练阶段就感知到量化误差。相比训练完成后直接做 PTQ训练后量化QAT 通常能保留更高的精度。它的实现思路大致是在训练过程中插入“伪量化节点”前向传播时执行量化再反量化。反向传播时使用直通估计器近似梯度让参数适应量化误差。训练结束后导出为 INT8 或 INT4 推理模型。如果你使用的是 llama.cpp 或 GGUF 路线更常见的做法是先用原始权重微调再做 GGUF 量化例如将模型导出为不同精度的 GGUF 文件# 进入 llama.cpp 目录 python3 convert_hf_to_gguf.py \ /path/to/qwen3.5-merged \ --outfile qwen3.5-merged.gguf \ --outtype q8_0 # 进一步量化到 Q4_K_M ./build/bin/llama-quantize \ qwen3.5-merged.gguf \ qwen3.5-q4_k_m.gguf \ q4_k_m需要说明的是真正的 QAT 训练需要专门的量化框架和较大的算力直接使用torch.fake_quantize或 NVIDIA TensorRT Model Optimizer 会更规范。本文不展开完整 QAT 训练代码因为涉及具体框架和模型结构建议按官方文档操作。5.5 微调后的评估微调之后不要急着上线。先用一份“训练时没见过的测试集”评估效果。评估维度可以包括输出格式合规率是否严格输出了要求格式。答案准确性与标准答案的匹配程度。语义相似度使用 BERTScore 或人工评分。回归测试确认微调没有把模型的通用能力带偏。这里我们使用 lm-evaluation-harness 快速跑一个评测pip install lm-eval lm_eval \ --model hf \ --model_args pretrained./qwen3.5-merged \ --tasks cmmlu \ --num_fewshot 0 \ --batch_size autoHarness 在这里就是“评测控制器”它负责加载你的模型、准备评测集、统计指标。工程化落地时Harness 还可以扩展用来管理多个实验的评测记录。6. RAG 知识库实战6.1 RAG 核心链路RAG 的完整链路可以拆成五个环节文档加载 - 分块 - 向量化 - 索引存储 - 检索 - 注入 Prompt - 生成这里最容易出问题的是分块和检索质量。如果分块策略不合理再好的向量模型也救不回来。6.2 切块策略切块需要平衡上下文长度与语义完整性。常见策略如下切块方式适用场景注意点固定长度切块通用文档容易切断语义不适合长文本段落切块结构化文档保留较完整语义推荐优先递归字符切块半结构化文本需要设置分隔符优先级语义切块复杂业务文档实现成本高效果取决于模型切块长度建议从 256 到 1024 个 token 之间测试。切得太短上下文信息不完整切得太长向量检索精度下降且容易超出模型上下文限制。另外要保留块之间的重叠部分一般重叠 64 到 128 个 token避免关键信息恰好落在分块边界上。6.3 向量化与检索中文场景推荐使用 BGE 系列向量模型例如pip install sentence-transformers faiss-cpu索引构建与检索代码如下# 文件路径rag_index.py import json import numpy as np import faiss from sentence_transformers import SentenceTransformer embedder SentenceTransformer(BAAI/bge-large-zh-v1.5) # 1. 加载文档这里假设 docs.json 是分块后的文本列表 with open(chunks.json, r, encodingutf-8) as f: chunks json.load(f) doc_texts [item[content] for item in chunks] doc_vectors embedder.encode(doc_texts, normalize_embeddingsTrue) # 2. 构建 FAISS 索引 dimension doc_vectors.shape[1] index faiss.IndexFlatIP(dimension) index.add(np.array(doc_vectors).astype(float32)) # 3. 检索 def search(query, top_k3): q_vec embedder.encode([query], normalize_embeddingsTrue) scores, ids index.search(np.array(q_vec).astype(float32), top_k) results [] for i in ids[0]: results.append({text: doc_texts[i], score: float(scores[0][list(ids[0]).index(i)])}) return results这里的IndexFlatIP是内积索引配合归一化向量就等价于余弦相似度。如果文档量大可以换成faiss.IndexIVFFlat或faiss.IndexHNSWFlat来提升检索速度。6.4 完整 RAG 问答代码有了检索结果接下来拼 Prompt 并调用模型生成答案# 文件路径rag_qa.py import requests from rag_index import search OLLAMA_URL http://localhost:11434/api/chat MODEL_NAME qwen3.5:9b def build_rag_prompt(query, top_k3): results search(query, top_ktop_k) context \n\n.join([r[text] for r in results]) prompt f请基于以下给定的资料回答问题。 参考资料 {context} 问题{query} 要求 1. 如果资料中能找到答案直接给出结论并标注依据来源。 2. 如果资料中没有提到明确回答“资料中未提及”不要编造。 3. 回答控制在 200 字以内。 return prompt def rag_chat(question): prompt build_rag_prompt(question) payload { model: MODEL_NAME, messages: [ {role: user, content: prompt} ], stream: False } resp requests.post(OLLAMA_URL, jsonpayload, timeout120) return resp.json()[message][content] if __name__ __main__: while True: q input(请输入问题输入 exit 退出) if q exit: break print(rag_chat(q))在 RAG 上面现在又出现了 Ontology RAG、Agentic RAG 等概念。本质是在基础 RAG 之上增加了实体关系图谱、多轮检索改写或自动路由能力。对于大多数业务场景先把基础 RAG 做好把切块、向量模型、检索召回率调到位再决定是否引入更重的框架。7. Agent 与 ReAct 模式实战7.1 ReAct 原理ReAct 是 Reasoning Acting 的组合。它让模型交替输出“思考”和“行动”再根据行动结果更新下一步思考。一个典型的 ReAct 输出循环如下Thought用户想查询北京天气我需要调用天气查询工具。 Actionget_weathercity北京 Observation北京今天多云气温 24℃ Thought我已经得到天气信息可以直接回答用户。 Answer北京今天多云气温 24℃。实现 Agent 时你需要做两件事一是解析模型输出的 Action 内容和参数二是根据 Action 找到本地注册的工具并执行。7.2 Agent 的循环控制下面给出一个最小可用的 Agent 实现仍然是基于 Ollama HTTP API# 文件路径simple_agent.py import requests OLLAMA_URL http://localhost:11434/api/chat MODEL_NAME qwen3.5:9b # 1. 注册工具 TOOLS { get_weather: { description: 查询指定城市天气参数格式city城市名, execute: lambda city: f{city}今天多云气温 24℃ }, calc: { description: 计算数学表达式参数格式expr表达式, execute: lambda expr: str(eval(expr)) } } def call_llm(messages): payload { model: MODEL_NAME, messages: messages, stream: False, options: {temperature: 0.2} } resp requests.post(OLLAMA_URL, jsonpayload, timeout120) return resp.json()[message][content] def parse_action(reply): # 简化版解析查找 Action: 后面的内容 if Action: not in reply: return None, None line reply.split(Action:)[1].strip().split(\n)[0] if in line: tool_name, _, param line.partition() else: tool_name, _, param line.partition(,) return tool_name.strip(), param.strip() def run_agent(prompt, max_steps5): messages [ { role: system, content: ( 你是 Agent 控制器。请使用 ReAct 模式工作。\n 可调用工具get_weathercalc。\n 每次输出格式\n Thought你的思考\n Action工具名参数\n 或者直接Answer最终答案 ) }, {role: user, content: prompt} ] for step in range(max_steps): reply call_llm(messages) print(f Step {step 1} ) print(reply) if Answer: in reply: return reply tool_name, param parse_action(reply) if tool_name is None: # 模型没有输出 Action 或 Answer追加提示让它继续 messages.append({role: assistant, content: reply}) messages.append({ role: user, content: 请继续输出 Action 或 Answer。 }) continue tool TOOLS.get(tool_name.strip()) if tool is None: observation f错误未找到工具 {tool_name} else: # 解析参数简化处理 keyvalue param_dict {} for pair in param.split() if in param else param.split(,): if in pair: k, v pair.split(, 1) param_dict[k.strip()] v.strip() try: observation tool[execute](*param_dict.values()) except Exception as e: observation f工具执行异常{str(e)} messages.append({role: assistant, content: reply}) messages.append({role: user, content: fObservation{observation}}) return 已达到最大步数任务终止。 if __name__ __main__: result run_agent(北京天气怎么样顺便计算 12 * 8) print(\n最终结果) print(result)7.3 Harness 是什么与 Agent 的关系Harness 在很多语境下被翻译成“脚手架”或“控制框架”。在模型评测里Harness 负责统一加载数据集、执行评测循环在 Agent 开发里Harness 类似 Agent 运行时的“总控台”负责调度模型、工具、记忆和错误恢复。很多开源框架会把 Agent 和执行 Harness 分开设计。Agent 负责决策逻辑Harness 负责基础设施比如日志记录、API 重试、超时处理、并发控制。你在设计工程架构时也应该把这两层分开避免后续想换模型或换工具时牵一发动全身。7.4 Agent 开发注意事项Agent 最常见的线上事故是“循环执行不终止”和“工具参数解析失败”要为 Agent 设置最大步数上限避免死循环消耗资源。要给工具调用加超时和异常捕获不能让工具崩溃拖垮整个 Agent。工具返回结果要精简过长的 Observation 会挤占模型上下文。关键决策路径要打印日志便于回溯。如果模型在 Agent 场景经常出现工具名拼写错误或格式错误可以考虑升级 Prompt或者做少量 Agent 轨迹数据的微调让模型更稳定地输出 Action 格式。8. 常见问题与排查清单8.1 高频报错列表问题现象常见原因解决思路拉取模型时连接中断网络问题配置国内镜像源或手动下载 GGUF 文件模型运行后输出乱码分词器不匹配下载模型时同时下载 tokenizer确认与模型配套调用 API 返回 invalid prompt输入触发内容安全策略调整措辞避免敏感词检查业务合规性提示 prompt is too long输入超出上下文窗口缩短 Prompt或增大-c上下文参数微调时 CUDA out of memory显存不足降低 batch size、开启梯度累积、使用 4bit 量化加载Agent 执行中报 agent terminated due to error模型输出格式非法或工具异常增加格式约束、捕获工具异常、设置重试机制RAG 检索结果不相关切块策略不合理或向量模型不匹配调整切块长度换用更适合中文的向量模型8.2 Prompt 过长如何解决有开发者遇到过这样的报错prompt is too long ... automatic compaction failed: api error: 400 unsupported这说明输入 Prompt 超过了模型上下文限制同时自动压缩又失败了。解决办法有几种手动压缩 Prompt去掉冗余内容。使用 RAG 只保留检索到的关键片段。增加模型的上下文窗口长度例如在 llama.cpp 中调大-c参数。将多轮历史对话做摘要只保留最近几轮。8.3 排查 checklist如果整体链路跑不通按下面的顺序排查先单独测试模型 API排除模型服务问题。再测试向量检索直接打印检索结果确认召回内容是否合理。然后测试 Prompt 拼接检查是否有格式错误。最后测试 Agent 循环确认工具解析和调用是否正常。每一步都保留日志不要跳过中间环节直接看最终结果。9. 最佳实践与工程建议9.1 根据场景选择技术方案不要为了“用技术而用技术”。推荐按以下分级标准化问答场景Prompt 少量示例即可。私有文档问答Prompt RAG。多工具多步骤任务Prompt ReAct Agent。输出格式要求极高、风格固定在 RAG/Agent 基础上做 LoRA 微调。低资源部署GGUF 量化 llama.cpp必要时做 QAT。9.2 数据与配置管理这里特别强调三条工程纪律模型文件、向量库、配置文件要通过版本管理工具管理记录每一次变更。微调实验要保留 base model、LoRA 权重、训练数据、评测结果四件套方便回溯。提示词不要散落在业务代码中集中放在配置中心或单独的模板文件里。9.3 安全与合规大模型落地时安全边界一定要提前规划对用户输入和模型输出做内容安全过滤。不要直接使用来源不明的“去限制”或“uncensored”模型这类模型往往存在严重合规风险也可能被植入恶意指令。涉及生产环境变更时先备份模型和向量库先在测试环境验证。对 Agent 的工具权限做最小化授权不要让模型拥有任意执行命令的权限。9.4 性能优化性能优化可以从几个层面入手推理层使用 vLLM 替代原始 Transformers 推理提升吞吐量。检索层为 FAISS 索配置 GPU 版本或者换用 Milvus 等分布式向量库。缓存层对高频问题做语义缓存相同或相似问题直接返回缓存结果。并发层把模型服务拆成独立集群避免与业务服务互相影响。10. 总结与下一步学习路线一轮走下来你已经能搭建一个“本地模型 Prompt 调优 RAG 知识库 简单 Agent”的完整链路。这套链路覆盖了目前大模型应用开发的绝大多数高频场景。下一步建议按这个顺序继续深入先动手跑通 Ollama 或 llama.cpp 部署把模型调用接口调熟。找一个真实的业务文档做 RAG反复调整切块策略观察检索效果。尝试用 LoRA 微调一个特定任务比如日志改写、工单分类体验从数据准备到权重合并的完整流程。再尝试把 Agent 接到你的工具系统比如数据库查询、HTTP API 调用注意加上步数上限和异常处理。最后可以考虑深入学习 vLLM 推理优化、分布式微调、QAT 等工程方向。大模型应用开发的核心不是“背 API”而是搞清楚每一层方案解决什么问题、成本是多少、边界在哪里。建议先跑通最小闭环再逐步叠加模块这样遇到问题时才不会一团乱麻。如果本文对你有帮助可以收藏备用后续我也会继续补充更多关于 Qwen 系列微调和 RAG 实战的细节。