网站图标怎么换桂林公司网站搭建
2026/4/18 1:09:49 网站建设 项目流程
网站图标怎么换,桂林公司网站搭建,网络营销推广工具有哪些,南京广告公司一览表各位同仁#xff0c;各位技术爱好者#xff0c;大家好#xff01;今天#xff0c;我们齐聚一堂#xff0c;共同探讨生成式AI领域中两个至关重要且常被拿来比较的概念#xff1a;Retrieval Augmented Generation (RAG) 和 Fine-tuning (微调)。随着大型语言模型#xff0…各位同仁各位技术爱好者大家好今天我们齐聚一堂共同探讨生成式AI领域中两个至关重要且常被拿来比较的概念Retrieval Augmented Generation (RAG)和Fine-tuning (微调)。随着大型语言模型LLMs的普及我们面临的挑战不再仅仅是如何使用它们更是如何高效、精准、经济地将它们应用于特定业务场景。我们常常会听到这样的疑问我的LLM不够聪明它不知道我们公司的内部规章制度它也无法以我们期望的语气与客户交流。面对这些问题我们应该选择在LangChain这样的框架中塞入大量上下文也就是RAG还是应该投入资源去微调一个模型呢这并非一个简单的二元选择题。作为编程专家我们的职责是深入理解这两种方案的原理、优势、局限性并根据具体的业务需求、数据特点和资源预算做出最明智的战略决策。今天的讲座我将带大家抽丝剥茧深入剖析RAG与Fine-tuning尤其聚焦于在何种场景下我们应该果断选择微调模型而非仅仅依赖上下文填充。一、生成式AI的挑战与解决方案概览大型语言模型如GPT系列、Llama系列以其惊人的通用知识和强大的语言理解与生成能力彻底改变了我们与信息交互的方式。然而这些模型并非万能。它们普遍存在以下几个核心局限知识截止日期 (Knowledge Cut-off):预训练模型的数据集通常有其截止日期这意味着它们无法获取并利用最新的实时信息。领域特异性知识缺乏 (Lack of Domain-Specific Knowledge):尽管模型知识广博但在高度专业化、私有的领域如企业内部文档、特定行业规范面前它们往往束手无策。“幻觉”现象 (Hallucination):模型有时会生成听起来合理但实际上是虚假或不准确的信息。行为与风格固化 (Fixed Behavior and Style):模型的输出风格、语气、遵循的规范等是其预训练过程中形成的难以直接调整以适应特定品牌或应用的要求。上下文窗口限制 (Context Window Limitations):虽然上下文窗口不断扩大但将所有相关信息塞入单个提示仍然是昂贵且有限的。为了克服这些挑战RAG和Fine-tuning应运而生成为最主流的两类解决方案。它们从不同的角度增强了LLM的能力但其内在机制和适用场景却大相径庭。二、理解RAG (Retrieval Augmented Generation)在LangChain中塞上下文RAG的核心思想非常直观当LLM需要回答一个问题时我们首先从一个外部知识库中检索出最相关的几段信息然后将这些信息作为额外的上下文与用户的问题一起提供给LLM引导它生成回答。这种方法有效地将模型的知识范围从其训练数据扩展到了任意可检索的外部数据。让我们通过LangChain这个流行的框架来深入理解RAG的工作流程和实现。2.1 RAG的工作流详解一个典型的RAG流程包含以下几个关键步骤数据加载 (Data Loading):从各种来源文档、数据库、网页等加载非结构化或半结构化数据。文档分割 (Document Splitting):将加载的文档分割成更小、更易于管理的块chunks。这是因为LLM的上下文窗口是有限的并且更小的块有助于提高检索精度。嵌入 (Embedding):使用一个嵌入模型Embedding Model将每个文本块转换成高维向量。这些向量捕获了文本的语义信息。向量存储 (Vector Store):将文本块及其对应的向量存储到向量数据库中。向量数据库能够高效地执行相似度搜索。检索 (Retrieval):当用户提出问题时首先将用户问题转换为向量。然后在向量数据库中搜索与问题向量最相似的文本块。生成 (Generation):将检索到的文本块作为上下文和原始用户问题一起发送给LLM。LLM利用这些上下文生成最终的回答。2.2 LangChain实现RAG的示例代码LangChain提供了一套模块化的工具极大地简化了RAG管道的构建。以下是一个使用LangChain实现RAG的简化示例假设我们有一个本地的PDF文档作为知识库。import os from langchain_community.document_loaders import PyPDFLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.embeddings import OpenAIEmbeddings from langchain_community.vectorstores import Chroma from langchain_community.chat_models import ChatOpenAI from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate # 假设你已经设置了OPENAI_API_KEY环境变量 # os.environ[OPENAI_API_KEY] YOUR_OPENAI_API_KEY print(--- RAG流程开始 ---) # 1. 数据加载 (Data Loading) # 假设我们有一个名为 company_policy.pdf 的公司政策文件 pdf_path ./company_policy.pdf # 为了运行示例我们创建一个假的PDF文件 with open(pdf_path, w) as f: f.write(## 公司差旅报销政策nn) f.write(所有员工在出差前需提交差旅申请并获得部门经理批准。) f.write(经济舱机票和标准酒店住宿费用可报销。) f.write(餐费报销上限为每天200元人民币。) f.write(报销申请需在差旅结束后10个工作日内提交并附上所有相关发票。) f.write(未经批准的额外费用将不予报销。nn) f.write(## 员工福利政策nn) f.write(公司为全职员工提供医疗保险、带薪年假每年15天和健身房补贴。) f.write(新入职员工在试用期结束后即可享受所有福利。) f.write(健身房补贴每月100元需提供会员证明。) print(f1. 加载文档: {pdf_path}) loader PyPDFLoader(pdf_path) documents loader.load() print(f 加载了 {len(documents)} 页文档。) # 2. 文档分割 (Document Splitting) print(2. 分割文档...) text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个块的最大字符数 chunk_overlap50 # 块之间的重叠字符数有助于保留上下文 ) chunks text_splitter.split_documents(documents) print(f 分割成 {len(chunks)} 个文本块。) # 3. 嵌入 (Embedding) 和 4. 向量存储 (Vector Store) print(3. 创建嵌入并存储到向量数据库 (Chroma)...) # 使用OpenAI的嵌入模型 embeddings OpenAIEmbeddings() # 使用Chroma作为本地向量数据库持久化存储 vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory./chroma_db # 持久化目录 ) vectorstore.persist() print( 向量数据库已创建并持久化。) # 5. 检索 (Retrieval) print(4. 构建检索器...) retriever vectorstore.as_retriever(search_kwargs{k: 3}) # 检索最相似的3个块 # 6. 生成 (Generation) print(5. 构建RAG链...) # 使用OpenAI的Chat模型作为LLM llm ChatOpenAI(model_namegpt-3.5-turbo, temperature0) # 定义一个更具体的Prompt模板 prompt_template 你是一个友好的公司政策助手。请根据提供的上下文信息回答用户的问题。 如果上下文中没有足够的信息请礼貌地告知用户你无法回答。 上下文: {context} 问题: {question} 回答: PROMPT PromptTemplate(templateprompt_template, input_variables[context, question]) # 创建RetrievalQA链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_typestuff, # 将所有检索到的文档直接填充到prompt中 retrieverretriever, return_source_documentsTrue, # 返回检索到的源文档 chain_type_kwargs{prompt: PROMPT} # 使用自定义Prompt ) # 示例查询 print(n--- 进行查询 ---) query1 公司差旅报销的餐费上限是多少 print(f问题1: {query1}) result1 qa_chain({query: query1}) print(f回答1: {result1[result]}) print(f来源文档1: {[doc.metadata for doc in result1[source_documents]]}n) query2 新员工何时能享受公司福利 print(f问题2: {query2}) result2 qa_chain({query: query2}) print(f回答2: {result2[result]}) print(f来源文档2: {[doc.metadata for doc in result2[source_documents]]}n) query3 公司是否提供购房补贴 print(f问题3: {query3}) result3 qa_chain({query: query3}) print(f回答3: {result3[result]}) print(f来源文档3: {[doc.metadata for doc in result3[source_documents]] if result3[source_documents] else 无相关文档}n) print(--- RAG流程结束 ---) # 清理生成的假PDF和向量数据库 os.remove(pdf_path) # shutil.rmtree(./chroma_db) # 如果需要彻底清理取消注释2.3 RAG的优点实时性与知识更新知识库可以独立于LLM进行更新只需更新向量数据库即可无需重新训练模型。这使得RAG非常适合处理需要最新信息或频繁变化的知识。可解释性与可追溯性由于回答是基于检索到的特定文档片段生成的用户可以追溯到信息的来源增加了透明度和信任度。减少幻觉通过将LLM限制在提供的上下文中RAG能够有效减少模型“编造”信息的风险。成本相对低廉不需要进行昂贵的模型训练主要成本在于嵌入生成、向量数据库维护和LLM的推理调用。无需改变模型RAG不改变LLM本身的参数这使其兼容性强可以与各种现有LLM配合使用。2.4 RAG的局限性依赖检索质量如果检索到的上下文不准确、不完整或不相关LLM的回答质量将大打折扣甚至可能产生误导。上下文窗口限制尽管检索可以筛选出最相关的信息但如果相关信息量仍然非常大或者问题需要整合大量分散的知识点仍可能超出LLM的上下文窗口。无法改变模型“行为”或“风格”RAG本质上是在“喂”给模型更多信息但它不能改变模型固有的输出风格、语气、价值观或推理能力。例如你无法通过RAG让模型变得更幽默或更严谨。复杂推理能力受限对于需要跨多个文档进行复杂逻辑推理、归纳总结或抽象概念理解的任务RAG可能显得力不从心。LLM本身进行复杂推理的能力仍然受限于其原始训练。Prompt工程的挑战如何设计有效的Prompt来引导LLM利用检索到的上下文并处理边缘情况如上下文不足仍然是一个挑战。三、理解Fine-tuning (微调模型)深入改变LLMFine-tuning即微调是在预训练模型的基础上使用特定任务或领域的数据集进行进一步训练的过程。它的目标是调整模型的内部参数使其更好地适应特定任务的需求甚至改变其行为模式、输出风格或内化特定领域的知识。3.1 Fine-tuning的核心思想与类型微调不是从头开始训练一个模型而是在一个已经具备强大通用能力的基座模型上进行“塑形”。这就像一个熟练的雕塑家在已经粗具形状的石膏像上进行精雕细琢使其更符合特定的艺术风格或人物形象。根据微调的程度和方式主要分为以下几种类型全参数微调 (Full Fine-tuning):原理在预训练模型的所有层上解冻所有参数并在新的数据集上进行训练。特点效果通常最好但计算资源需求巨大训练时间长需要大量高质量的标注数据且容易发生灾难性遗忘catastrophic forgetting。高效参数微调 (PEFT – Parameter-Efficient Fine-Tuning):原理只训练模型的一小部分参数或者引入少量新的、可训练的参数而冻结大部分预训练参数。特点显著减少计算资源需求和训练时间降低数据量要求同时能有效避免灾难性遗忘。是目前生产环境中微调LLM的主流方式。常见PEFT方法LoRA (Low-Rank Adaptation):在预训练模型的原始权重矩阵旁边注入低秩矩阵对只训练这些小型的矩阵对。推理时将这些适配器与原始权重合并。QLoRA (Quantized LoRA):在LoRA的基础上进一步将基座模型量化到4位进一步降低内存占用。Prefix Tuning, P-Tuning, Prompt Tuning:通过在输入序列前添加可训练的“前缀”或“提示”向量来引导模型而不修改模型本身的参数。3.2 Fine-tuning的工作流一个完整的Fine-tuning流程通常包括数据准备 (Data Preparation):这是微调中最关键的一步。需要收集和清洗高质量的、符合特定格式通常是指令-响应对或对话历史的数据集。数据的质量和数量直接决定了微调的效果。选择基座模型 (Base Model Selection):根据任务需求、可用资源和许可协议选择一个合适的预训练LLM。选择微调策略 (Fine-tuning Strategy):根据数据量、计算资源和性能需求决定采用全参数微调还是PEFT如LoRA。训练 (Training):使用选定的数据集和策略在GPU等计算资源上运行微调过程。评估 (Evaluation):在独立的测试集上评估微调模型的性能通常使用任务特定的指标。部署 (Deployment):将微调后的模型部署到生产环境供应用程序调用。3.3 PEFT (LoRA) 实现Fine-tuning的示例代码考虑到实际应用中PEFT的普遍性我们以LoRA为例展示如何使用transformers和peft库进行模型微调。这里我们假设要微调一个模型使其能以特定风格回答问题。import torch from transformers import AutoTokenizer, AutoModelForCausalLM, TrainingArguments, Trainer from peft import LoraConfig, get_peft_model, prepare_model_for_kbit_training from datasets import Dataset # 假设你已经安装了datasets库 # 假设你已经设置了HUGGING_FACE_HUB_TOKEN环境变量 # os.environ[HUGGING_FACE_HUB_TOKEN] YOUR_HF_TOKEN print(--- Fine-tuning (LoRA) 流程开始 ---) # 1. 数据准备 (Data Preparation) # 准备一个包含指令-响应对的微调数据集 # 假设我们想要模型以“积极乐观且略带幽默”的风格回答问题 data [ {instruction: 请告诉我今天天气怎么样, output: 哇今天真是阳光明媚心情都跟着飞扬起来了仿佛整个世界都在对你微笑呢}, {instruction: 介绍一下Python编程语言。, output: Python这位编程界的明星它就像一位多才多艺的朋友能帮你搞定从网站开发到人工智能的各种酷炫项目。语法简洁优雅学起来简直是小菜一碟}, {instruction: 给我一个建议如何提高工作效率, output: 想提高效率秘诀就是把大象切成小块吃掉哦不我是说把大任务拆分成小目标再搭配番茄工作法你会发现时间就像被施了魔法一样}, {instruction: 解释一下什么是量子力学。, output: 量子力学啊那可是个充满奇幻色彩的领域它告诉我们微观世界里的一切都那么不可思议粒子可以同时存在于多个地方简直比魔术还精彩准备好颠覆你的世界观了吗}, ] # 将数据转换为Dataset对象 # 为了简化这里直接从列表创建实际中可能从CSV, JSON等加载 def generate_prompt(example): return f### 指令:n{example[instruction]}nn### 回答:n{example[output]} processed_data [{text: generate_prompt(item)} for item in data] dataset Dataset.from_list(processed_data) print(f1. 数据集准备完成共 {len(dataset)} 条数据。) print( 示例数据格式:) print(dataset[0][text]) # 2. 选择基座模型 (Base Model Selection) # 我们选择一个小型且易于微调的模型作为示例如 Mistral-7B-v0.1 # 注意Mistral-7B需要足够的GPU内存对于低内存设备可能需要更小的模型或更 aggressive 的量化 model_name mistralai/Mistral-7B-v0.1 print(fn2. 加载基座模型和分词器: {model_name}) # 加载分词器 tokenizer AutoTokenizer.from_pretrained(model_name) tokenizer.pad_token tokenizer.eos_token # 设置pad token tokenizer.padding_side right # 对于因果语言模型通常右侧填充 # 加载模型使用4位量化以节省内存 (QLoRA) # 注意你需要安装bitsandbytes库 model AutoModelForCausalLM.from_pretrained( model_name, load_in_4bitTrue, # 启用4位量化 device_mapauto, torch_dtypetorch.float16 # 使用float16以节省内存和加速训练 ) # 准备模型进行kbit训练 (QLoRA特有步骤) model prepare_model_for_kbit_training(model) print( 模型已加载并准备好进行kbit训练。) # 3. 配置LoRA (PEFT) print(n3. 配置LoRA...) lora_config LoraConfig( r8, # LoRA的秩决定了适配器矩阵的大小通常是8、16、32、64 lora_alpha16, # LoRA缩放因子 target_modules[q_proj, k_proj, v_proj, o_proj, gate_proj, up_proj, down_proj], # 目标模块通常是注意力层的投影矩阵 lora_dropout0.05, # LoRA层的Dropout biasnone, # 不对偏置项进行微调 task_typeCAUSAL_LM, # 任务类型为因果语言建模 ) # 获取PEFT模型 model get_peft_model(model, lora_config) print( LoRA适配器已添加到模型。) model.print_trainable_parameters() # 打印可训练参数量 # 对数据集进行tokenization def tokenize_function(examples): # 将文本截断到模型最大长度并确保所有输入都填充到最大长度 return tokenizer( examples[text], truncationTrue, max_length512, # 最大输入长度 paddingmax_length ) tokenized_dataset dataset.map(tokenize_function, batchedTrue) # 移除原始text列因为我们现在有input_ids, attention_mask tokenized_dataset tokenized_dataset.remove_columns([text]) # 将label设置为input_ids因为我们是在进行因果语言建模模型预测下一个token tokenized_dataset tokenized_dataset.rename_column(input_ids, labels) # 4. 设置Trainer (using transformers) print(n4. 设置训练参数...) training_args TrainingArguments( output_dir./fine_tuned_model, num_train_epochs3, per_device_train_batch_size2, # 根据GPU内存调整 gradient_accumulation_steps4, # 梯度累积步数模拟更大的batch size learning_rate2e-4, fp16True, # 混合精度训练 save_strategyepoch, logging_steps10, report_tonone, # 可以设置为wandb等进行可视化 ) trainer Trainer( modelmodel, argstraining_args, train_datasettokenized_dataset, tokenizertokenizer, ) # 5. 训练 (Training) print(n5. 开始训练模型...) trainer.train() print( 模型训练完成。) # 6. 保存微调后的模型 (LoRA适配器) print(n6. 保存LoRA适配器...) lora_adapter_path ./lora_adapters trainer.model.save_pretrained(lora_adapter_path) tokenizer.save_pretrained(lora_adapter_path) # 保存分词器 print(f LoRA适配器和分词器已保存到: {lora_adapter_path}) # 7. (可选) 合并适配器并保存完整模型 # 如果你想得到一个可以直接加载的完整微调模型而不仅仅是适配器 print(n7. (可选) 合并LoRA适配器到基座模型并保存完整模型...) # 重新加载基座模型 base_model AutoModelForCausalLM.from_pretrained( model_name, return_dictTrue, torch_dtypetorch.float16, device_mapauto, ) # 加载LoRA适配器并合并 from peft import PeftModel model_to_merge PeftModel.from_pretrained(base_model, lora_adapter_path) merged_model model_to_merge.merge_and_unload() # 合并并卸载LoRA参数 merged_model_path ./merged_fine_tuned_model merged_model.save_pretrained(merged_model_path) tokenizer.save_pretrained(merged_model_path) print(f 合并后的完整模型已保存到: {merged_model_path}) print(--- Fine-tuning (LoRA) 流程结束 ---) # 简单的推理测试 (使用合并后的模型) print(n--- 进行推理测试 (使用合并后的模型) ---) # 确保在CPU或GPU上运行 device cuda if torch.cuda.is_available() else cpu merged_model.to(device) merged_model.eval() test_prompt ### 指令:n请给我讲一个笑话。nn### 回答: input_ids tokenizer(test_prompt, return_tensorspt).input_ids.to(device) with torch.no_grad(): outputs merged_model.generate( input_ids, max_new_tokens100, do_sampleTrue, top_k50, top_p0.95, temperature0.7 ) response tokenizer.decode(outputs[0], skip_special_tokensTrue) print(f微调模型生成的回答:n{response})注意运行上述代码需要安装transformers,peft,bitsandbytes,accelerate,trl,datasets等库。特别是bitsandbytes和accelerate对于QLoRA至关重要。trl库在实际场景中常用于SFTTrainer提供了更高级的微调功能。由于Mistral-7B模型较大即使是QLoRA也需要至少16GB以上的GPU内存。对于资源有限的用户可以选择更小的模型如google/gemma-2b或facebook/opt-125m进行实验。3.4 Fine-tuning的优点改变模型行为和风格这是微调最独特的优势。通过在特定数据集上训练模型可以学习并模仿特定的语气、输出格式、编码规范等使其输出与品牌或产品形象高度一致。内化领域知识和复杂推理模型通过训练能够“真正理解”并内化特定领域的知识而不仅仅是引用。这使其能够在该领域进行更深层次的、多步骤的复杂推理和问题解决。提升特定任务性能对于分类、摘要、命名实体识别、情感分析等特定NLP任务微调模型通常能达到比通用LLM更好的性能。缩短提示 (Prompt) 长度由于模型已经内化了相关知识和行为推理时所需的Prompt可以更简洁从而降低推理成本和延迟。潜在的推理成本降低虽然训练成本高昂但如果微调后模型可以更高效地处理任务例如更短的Prompt或使用更小但经过微调的模型长期来看可能降低推理阶段的成本。3.5 Fine-tuning的局限性数据量和数据质量要求高微调需要大量高质量、经过精心标注的特定格式指令-响应对数据。数据的偏见、错误或不足都将直接影响微调效果。计算资源消耗大即使是PEFT也需要GPU等计算资源进行训练。全参数微调则更是资源密集型操作。成本高昂除了计算资源数据标注、模型工程师的人力成本也较高。难以实时更新知识一旦知识发生变化需要重新收集数据、重新微调、重新部署模型这个过程耗时耗力不适合需要实时更新的场景。需要模型工程专业知识微调涉及模型选择、超参数调整、评估指标等需要具备深入的机器学习和深度学习知识。可能导致灾难性遗忘尤其在全参数微调中模型可能会“忘记”部分通用知识。四、RAG vs Fine-tuning何时选择微调模型而不是在LangChain里塞上下文现在我们来到了今天讲座的核心在什么场景下我们应该优先考虑微调模型而非仅仅依赖RAG核心的决策点在于你的目标是什么你需要改变模型“学到的知识”还是“行为/能力”让我们通过具体的场景来详细分析。4.1 场景一模型需要学习新的“行为模式”或“风格”问题你的LLM在回答客户问题时总是过于官方、冷淡或者输出格式不符合公司品牌指南。你希望它能以更友好、更专业、更幽默或更符合特定行业术语的方式进行交流并且输出内容有固定的结构如总结、要点、行动建议。RAG的局限RAG只能提供信息无法改变模型的内在生成机制和风格。无论你塞入多少“友好”的上下文模型仍然会以其预训练时形成的风格来处理这些信息。微调的优势通过在包含期望风格、语气和格式的指令-响应对数据集上进行微调例如让模型模仿客服专家的对话风格或者遵循特定的JSON输出格式模型能够内化这些行为模式。它将学会不仅仅是回答问题更是以“你想要的方式”回答问题。示例代码片段微调训练数据[ {instruction: 解释一下我们的退货政策。, output: 当然亲爱的顾客我们的退货政策非常简单明了。您可以在收到商品后的30天内凭借有效购物凭证进行退货。请确保商品保持原样未被使用哦}, {instruction: 请用我们公司的代码风格生成一个Python函数。, output: 好的这是遵循我们内部PEP8规范和文档注释习惯的Python函数nnpythonndef calculate_discount(price: float, discount_rate: float) - float:n n 计算商品的折扣价格。nn Args:n price (float): 商品原价。n discount_rate (float): 折扣率 (例如0.10 表示10%折扣)。nn Returns:n float: 折扣后的价格。n n if not (0 discount_rate 1):n raise ValueError(折扣率必须在0到1之间。)n return price * (1 - discount_rate)n} ]4.2 场景二模型需要内化高度专业化或私有的领域知识并进行复杂推理问题你的应用场景涉及医疗诊断辅助、复杂金融风险评估、特定工程设计或法律条款分析等。这些领域不仅包含大量私有且专业的数据还需要模型在这些数据上进行多步骤的、深层次的逻辑推理和信息整合而不仅仅是简单地引用。例如根据多个临床指标和患者病史给出初步诊断建议。RAG的局限尽管RAG可以检索相关文档但它受限于LLM的上下文窗口难以将所有必要的、分散的专业知识一次性提供给LLM进行复杂的交叉分析。此外LLM在面对高度专业的推理任务时其通用推理能力可能不足以处理领域内的细微差别和隐含关系。它更多是“读取”和“总结”而非“理解”和“推断”。微调的优势通过在结构化、高质量的领域数据如带有专业问答对、诊断案例、法规解读的文本上进行微调模型能够真正“学习”这些专业知识并在参数中内化这些领域的推理模式。它不再仅仅是信息的检索者而是成为了一个具备领域专业能力的“思考者”。微调使模型能够更好地理解领域术语、概念之间的关系并执行更复杂的逻辑链。示例代码片段微调训练数据[ {instruction: 请根据以下患者信息和实验室报告提供初步诊断建议[患者信息和报告]。, output: 根据提供的A、B、C指标结合患者病史初步诊断倾向于X疾病建议进一步进行Y检查以确诊。}, {instruction: 分析合同条款A和条款B之间的潜在冲突。, output: 条款A规定了...条款B规定了...。两者在关于[特定情境]的处理上存在潜在冲突可能导致[具体风险]。建议通过补充协议明确...} ]4.3 场景三需要缩短提示 (Prompt) 长度降低推理成本和延迟问题你的应用是高并发、大规模的生产系统每次LLM调用都需要尽可能低的延迟和成本。RAG每次都需要将检索到的几千甚至上万个token作为上下文发送给LLM这导致了高昂的API费用和较长的推理时间。RAG的局限RAG的本质决定了它需要将检索到的上下文塞入Prompt。虽然上下文窗口在增长但更多的输入token意味着更高的API费用和更长的处理时间。微调的优势通过微调模型已经将核心知识和行为内化到其参数中。这意味着在推理时你不再需要提供大量的上下文只需简洁的指令即可。模型可以基于其内部知识直接生成回答从而显著缩短Prompt长度降低每次调用的token费用和延迟。对于高频调用的场景这可以带来巨大的成本节约和性能提升。示例RAG Prompt:根据以下文档[大量公司政策文档]请问差旅报销的餐费上限是多少Fine-tuned Prompt:差旅报销的餐费上限是多少 (模型已通过微调学习了公司政策)4.4 场景四RAG的检索效果不佳或检索结果难以形成高质量上下文问题你的知识库数据结构复杂、信息分散或者查询与文档的语义匹配度不高导致RAG检索到的结果经常不准确、不完整或相互矛盾。或者某些复杂问题需要模型综合分析多个文档中的零散信息但RAG检索到的单个或少量片段不足以支撑这种综合性回答。RAG的局限RAG的性能瓶颈往往在检索阶段。如果嵌入模型无法准确捕捉语义或者文档分割不当或者向量数据库质量不高都将导致检索失败进而影响最终答案。对于高度抽象或需要跨领域知识融合的问题简单的相似度检索可能无法找到真正相关的上下文。微调的优势当RAG的检索效果成为瓶颈时微调提供了一个替代方案。通过在包含这些复杂、分散知识的问答对上训练模型模型可以学习如何直接处理和整合这些信息而不是依赖外部检索。这要求数据准备阶段投入大量精力去构造高质量的、能反映这些复杂性的训练样本。在某些情况下模型甚至能通过微调学习到更优的检索策略例如微调一个检索器或者微调一个能识别何时需要更多信息并生成子查询的LLM但这通常属于更高级的混合策略。4.5 场景五对模型幻觉的容忍度极低且知识相对稳定问题你的应用场景对错误信息或“幻觉”的容忍度极低例如在医疗、金融、法律等关键决策支持系统中。同时相关知识相对稳定不常发生变化。RAG的局限尽管RAG旨在减少幻觉但它并非完美。如果检索到的上下文本身存在错误、误导性或者LLM在整合上下文时出现偏差仍可能产生幻觉。此外RAG的可解释性虽然强但如果用户不仔细阅读来源仍可能被误导。微调的优势通过在精心策展和验证过的“黄金标准”数据集上进行微调模型可以被“教导”高度的准确性和事实性。由于知识被内化模型在生成时更倾向于依赖这些被验证过的信息。对于知识更新不频繁的场景微调提供了一种将准确性深度嵌入模型参数的方法从根本上降低了幻觉的风险。当然这需要极高的数据质量控制和持续的模型评估。4.6 场景六需要特定语言或术语的深度理解和生成问题你的应用需要处理特定方言、古文、专业黑话、或者某种小语种而这些内容在通用LLM的预训练数据中可能很少见导致模型理解和生成能力不足。RAG的局限RAG可以提供这些特定语言的文本但如果LLM本身对这些语言的理解不够深入它可能无法正确解析上下文中的细微语义也无法以地道的方言或专业术语进行生成。微调的优势通过在包含这些特定语言或术语的语料上进行微调模型可以显著提升对这些语言模式的识别、理解和生成能力。它会学习到这些语言的语法、词汇和表达习惯从而能够进行更准确、更自然的交互。示例代码片段微调训练数据[ {instruction: 请用上海话问候我。, output: 侬好伐今朝天气老好额}, {instruction: 解释一下N-P完全问题。, output: 在计算复杂度理论中N-P完全问题是指一类在多项式时间内可验证其解且其任意实例都可以在多项式时间内归约为其他N-P完全问题的判定问题。简单来说如果你能高效地解决其中一个就能高效解决所有这一类问题。} ]4.7 决策矩阵RAG vs Fine-tuning为了更清晰地呈现两者的选择逻辑我们可以构建一个决策矩阵特性/需求RAG (LangChain塞上下文)Fine-tuning (微调模型)何时选择微调核心目标提供最新/外部知识减少幻觉基于事实回答。改变模型行为、风格、内化特定领域知识提升特定任务性能。当需要改变模型固有行为、风格或深度内化复杂领域知识时。知识更新实时只需更新向量数据库。需重新训练/部署成本高。当知识相对稳定或者需要模型深度理解而非仅引用时。模型行为/风格无法改变。可以彻底改变。当需要模型以特定语气、格式、遵循特定规范输出时。推理能力依赖LLM本身受上下文限制。可以显著增强特定任务的复杂推理能力。当模型需要在特定领域进行高度专业化、复杂、多步的推理时。数据需求外部文档无需标签。高质量、指令-响应对需标注可能需要大量。当有高质量的、符合特定任务需求的标注数据时。计算资源低RAG链运行LLM推理成本。高训练LLM推理可能降低。当有充足的计算资源和时间并且预期长期效益如降低推理成本显著时。成本较低。较高训练成本推理成本可能降低。当初期投入可以带来长期效益或RAG方案无法满足性能要求时。可解释性强可追溯到源文档。弱黑盒模型。当可解释性不是首要关注点或通过其他方式如事后验证可接受时。幻觉控制较好但依赖检索质量。随训练数据质量提升理论上更少但仍可能发生。当对幻觉容忍度极低且通过精心构建训练数据可以有效缓解时。典型场景问答系统、聊天机器人、文档摘要。风格迁移、代码生成、专业领域机器人、情感分析、多语言任务。当RAG方案在性能、行为、风格、推理能力上无法满足要求时。五、混合策略RAG与Fine-tuning的结合在许多实际应用中RAG和Fine-tuning并非水火不容的替代品而是可以相互补充、协同工作的强大工具。最佳实践往往是两者的结合。想象一下这样的场景你希望你的客服机器人能够以品牌特定的友好语气回答客户的最新问题并且这些问题可能涉及公司最新的产品发布或促销活动。RAG处理实时/外部知识RAG组件负责从产品数据库或最新公告中检索相关信息。Fine-tuning处理行为/风格一个经过微调的LLM可以确保在接收到RAG提供的上下文后以公司期望的风格、语气和格式来组织和生成回答。这个微调模型可能在以下几个方面得到了增强风格和语气学习了客服人员的沟通方式。摘要能力学习了如何高效地从长篇检索文本中提取关键信息。结构化输出学习了如何将回答组织成易于理解的要点或表格。这种混合策略能够充分利用两者的优势微调模型提供了深层次的领域理解和行为控制而RAG则提供了动态、实时的外部知识补充。# 假设我们已经有一个微调过的模型merged_model和对应的tokenizer # 这个模型被微调为能够以“友好且简洁”的风格进行摘要和回答 # 省略了模型加载的代码假设merged_model和tokenizer已加载 # 重新定义RAG链但使用我们微调过的LLM # from langchain_community.llms import HuggingFacePipeline # 或者其他方式包装HuggingFace模型 # 假设merged_model已经加载并部署我们可以通过API或本地推理服务来调用它 # 这里为了演示我们假设可以直接使用transformers pipeline from transformers import pipeline # 假设我们已经有了合并后的模型和分词器 # merged_model_path ./merged_fine_tuned_model # fine_tuned_tokenizer AutoTokenizer.from_pretrained(merged_model_path) # fine_tuned_model AutoModelForCausalLM.from_pretrained(merged_model_path, device_mapauto, torch_dtypetorch.float16) # 创建一个HuggingFacePipeline来封装微调模型 # 实际生产中可能通过API Gateway调用这里是本地模拟 class FineTunedLLM: def __init__(self, model, tokenizer): self.pipeline pipeline( text-generation, modelmodel, tokenizertokenizer, max_new_tokens256, do_sampleTrue, temperature0.7, top_k50, top_p0.95, device_mapauto ) def generate(self, prompt: str) - str: # 为了兼容LangChain的LLM接口我们需要一个类似invoke的方法 # 或者直接作为ChatModel的代理 result self.pipeline(prompt) return result[0][generated_text][len(prompt):].strip() # 提取模型生成的部分 # 实例化微调LLM # fine_tuned_llm FineTunedLLM(fine_tuned_model, fine_tuned_tokenizer) # 实际使用时需要解注释 # 为了演示方便我们暂时用ChatOpenAI模拟一个“行为类似微调后”的模型 # 实际中这里会接入你部署的微调模型API或本地实例 from langchain_openai import ChatOpenAI fine_tuned_llm_for_rag ChatOpenAI(model_namegpt-3.5-turbo, temperature0.2) # 模拟一个更受控、风格一致的模型 print(n--- 混合策略RAG与Fine-tuning结合 ---) # 沿用之前的RAG组件 (loader, text_splitter, embeddings, vectorstore, retriever) # 假设它们已经初始化并可用 # 定义一个更具体的Prompt模板引导微调模型以特定风格处理检索到的上下文 hybrid_prompt_template 你是一个专业且友好的公司助手。请根据提供的上下文信息以简洁明了、积极乐观的语气回答用户的问题。 如果上下文中没有足够的信息请礼貌地告知用户你无法回答。 上下文: {context} 问题: {question} 回答: HYBRID_PROMPT PromptTemplate(templatehybrid_prompt_template, input_variables[context, question]) # 创建RetrievalQA链使用微调模型 hybrid_qa_chain RetrievalQA.from_chain_type( llmfine_tuned_llm_for_rag, # 这里使用微调模型实例 chain_typestuff, retrieverretriever, return_source_documentsTrue, chain_type_kwargs{prompt: HYBRID_PROMPT} ) # 示例查询 query_hybrid 请问公司最新发布的关于员工福利的通知有哪些亮点 print(f问题: {query_hybrid}) # 注意本示例中PDF文件内容不包含“最新发布的”福利通知所以结果会体现这一点 # 实际应用中RAG会检索到对应的最新文档 result_hybrid hybrid_qa_chain({query: query_hybrid}) print(f混合策略回答: {result_hybrid[result]}) print(f来源文档: {[doc.metadata for doc in result_hybrid[source_documents]]}n) print(--- 混合策略演示结束 ---)在这个例子中fine_tuned_llm_for_rag代表了我们已经微调好的模型。它接收RAG检索到的上下文和用户问题然后以其特有的风格和能力生成最终的回答。这种方式既保证了知识的实时性和广度通过RAG又确保了输出的专业性和一致性通过Fine-tuning。六、战略选择与未来展望深入理解RAG与Fine-tuning并非易事它们各自拥有独特的优势和局限。RAG以其灵活性、实时性和成本效益在许多场景中是首选尤其适用于需要频繁更新知识、对可解释性要求高的问答系统。它通过“外部记忆”增强了LLM的知识边界。然而当你的应用需要LLM真正改变其行为模式、输出风格、内化高度专业的领域知识进行复杂推理、显著降低推理成本或处理RAG难以有效应对的复杂语义场景时微调模型将成为不可替代的战略选择。微调是赋予LLM“新技能”和“新个性”的关键手段。更重要的是RAG和Fine-tuning并非互斥而是互补的。将两者结合的混合策略往往能够实现超越单一方案的最佳性能。随着PEFT技术如LoRA、QLoRA的不断成熟微调的门槛正在逐步降低使得更多的企业和开发者能够利用这一强大工具构建更智能、更符合业务需求的生成式AI应用。最终的决策始终围绕你的项目需求、数据可用性、计算资源预算以及对性能指标如准确性、延迟、成本、风格一致性的权衡。深入理解这些技术并根据实际情况灵活运用将是我们在AI时代取得成功的关键。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询