ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

中文金融知识微调LLaMA系模型:智能问答系统实战指南

中文金融知识微调LLaMA系模型:智能问答系统实战指南 简介面向中文金融领域NLP开发者与智能问答系统学习者这份资源围绕LLaMA系大模型的训练、微调与推理全流程展开重点解决金融专业术语理解与知识密集型问答的落地问题。包内共21个文件以json指令与金融语料、sh训练推理脚本、py核心代码为主辅以png流程示意图、md说明文档及txt依赖清单压缩包约1.66MB结构紧凑便于快速上手。已有2023人学习下载适合具备一定深度学习基础、希望掌握大模型微调与知识图谱融合策略的读者。资源提供训练与推理流水线示意图、金融指令数据集、prompter与模板配置、微调及对比测试脚本并给出知识图谱辅助推理的工程思路可帮助读者理解监督微调中的学习率调整、批次选择与早停策略以及实体链接与路径搜索在问答中的补充作用形成从数据准备到推理部署的完整参考。1. 中文金融知识喂给 LLaMA 系模型一套能跑通的问答系统长什么样金融领域的问答和通用闲聊完全是两码事。你问「这只票能不能买」通用模型敢给你编一段似是而非的股评你问「资管新规对结构化产品的影响」它可能把几年前的旧口径当现行规则讲。问题不在模型不够大而在它没见过你手里那批研报、公告、合规问答对。基于中文金融知识的 LLaMA 系微调模型做智能问答系统要解决的就是这件事把散落在 PDF、Excel、内部知识库里的中文金融语料变成模型能记住、能引用、能稳定输出的能力再包一层推理服务对外提供问答接口。这套方案适合三类人手里有金融语料想做私有化问答的团队、想拿 LLaMA 系模型练一遍「数据清洗—微调—推理—评测」全链路的工程师、以及被通用大模型幻觉坑过、想用领域数据把答案摁住的从业者。它不适合指望零数据、零算力就能出效果的人。下面按数据、微调、推理、评测、踩坑的顺序把每一步的参数和命令讲清楚新手能照着跑熟手能直接看边界。2. 数据先行把中文金融语料做成能微调的指令集2.1 金融语料的三种来源与清洗口径微调效果的上限由数据决定这句话在金融场景尤其成立。常见语料来源有三类一是公开研报和上市公司公告二是内部合规问答、客服工单、投顾话术三是监管文件与业务手册。三类数据的噪声完全不同——研报有大量图表残留和免责声明公告有固定格式的抬头和落款内部问答则口语化、缺上下文。清洗的核心目标是「去噪 补全 对齐」。去噪指删掉页眉页脚、图表编号、重复免责声明补全指把「如上所述」这类指代还原成具体主体对齐指把问答对整理成统一的指令格式。我一般会先做一轮规则清洗再用模型做一轮语义去重最后人工抽检 5% 左右。import re import hashlib def clean_finance_text(raw: str) - str: # 去掉页眉页脚常见的页码与免责声明 raw re.sub(r第\s*\d\s*页\s*/?\s*共\s*\d\s*页, , raw) raw re.sub(r免责声明[:].*?$, , raw, flagsre.S) # 合并被 PDF 拆断的句子 raw re.sub(r(?[\u4e00-\u9fa5])\n(?[\u4e00-\u9fa5]), , raw) # 压缩多余空白 raw re.sub(r[ \t\u3000], , raw) return raw.strip() def dedup_by_hash(texts, threshold0.9): seen, kept set(), [] for t in texts: h hashlib.md5(t[:200].encode()).hexdigest() if h not in seen: seen.add(h) kept.append(t) return keptclean_finance_text里三条正则分别处理页码、免责声明和断句dedup_by_hash用前 200 字做指纹去重适合处理大批量近似文本。参数上threshold这里没实际用到如果你换成 SimHash 或 MinHash可以把它设成 0.9 控制相似度阈值。注意别把表格里的数字当噪声删掉金融问答里数字往往就是答案本身。2.2 指令格式设计让模型学会「按金融口径回答」LLaMA 系微调常用 Alpaca 或 ShareGPT 两种格式。金融问答建议用带 system 的三段式把角色和约束写死减少模型自由发挥。{ system: 你是一名严谨的中文金融问答助手只依据给定知识回答不确定时明确说明。, instruction: 资管新规对结构化产品优先级有什么影响, input: 参考资料资管新规要求分级产品优先级与劣后级比例不得超过3:1……, output: 根据资管新规结构化产品优先级与劣后级的杠杆比例上限为3:1…… }system字段是约束模型行为的关键金融场景一定要写「不确定时明确说明」否则模型会硬编。input放检索到的参考资料这样微调出来的模型天然适配 RAG 流程。output要人工审核宁可少而准不要多而脏。一般 5000 到 20000 条高质量指令对就能看到明显效果低于 2000 条建议先做数据增强。2.3 用 Python 把 TXT 文档转成微调 JSON 数据集很多团队的原始语料就是一堆 TXT需要转成上节的 JSON 格式。下面脚本按「问题行 答案段」的约定切分适合内部问答文档。import json def txt_to_alpaca(path, out_path): with open(path, encodingutf-8) as f: blocks f.read().split(\n\n) # 空行分隔问答块 samples [] for b in blocks: lines [l.strip() for l in b.split(\n) if l.strip()] if len(lines) 2: continue q, a lines[0], .join(lines[1:]) samples.append({ system: 你是一名严谨的中文金融问答助手只依据给定知识回答。, instruction: q, input: , output: a }) with open(out_path, w, encodingutf-8) as f: for s in samples: f.write(json.dumps(s, ensure_asciiFalse) \n) txt_to_alpaca(finance_faq.txt, finance_alpaca.jsonl)切分逻辑依赖空行如果你的文档没有空行改成按「问」「答」标记切。输出用 JSONL 每行一条方便流式读取。ensure_asciiFalse保证中文不被转义这个参数漏了会导致数据集里全是\uXXXX训练时 tokenizer 处理会出问题。3. 微调实战LLaMA 系模型在中文金融场景的参数怎么设3.1 全量微调还是 LoRA显存与效果的取舍金融团队最常问的就是「我只有一两张卡能不能微调」。答案是能但要选对方法。全量微调 7B 模型FP16 下大约需要 80GB 以上显存单卡基本没戏LoRA 只训练低秩旁路7B 模型 24GB 显存就能跑效果在领域问答上能到全量微调的八九成。方式7B 显存需求训练速度领域效果适用场景全量微调80GB慢最好多卡、数据量大LoRA16-24GB快接近全量单卡、快速迭代QLoRA10-16GB较慢略低于 LoRA消费级显卡选型建议数据少于 1 万条、卡不多直接 LoRA要做长期迭代、数据持续增长再考虑全量。QLoRA 适合 4090 这类 24GB 卡但 4-bit 量化会带来一点精度损失金融数字类问答要谨慎。3.2 LoRA 关键参数rank、alpha、target_modulesLoRA 有三个参数决定成败lora_rank、lora_alpha、target_modules。rank 控制旁路矩阵的秩金融领域建议 8 到 32太小欠拟合太大容易过拟合且显存涨。alpha 一般设成 rank 的两倍缩放系数稳定。target_modules 决定往哪些层插旁路LLaMA 系常见做法是q_proj, k_proj, v_proj, o_proj全插只插 q、v 效果会打折。from peft import LoraConfig lora_config LoraConfig( r16, # 秩金融领域 8-32 lora_alpha32, # 通常为 r 的 2 倍 target_modules[q_proj, k_proj, v_proj, o_proj], lora_dropout0.05, # 小数据集防过拟合 biasnone, task_typeCAUSAL_LM )r16是金融问答的稳妥起点数据量上万可以提到 32。lora_dropout0.05在几千条数据时能明显抑制过拟合数据量大可以降到 0。biasnone是常规选择改成all会多训偏置项收益不明显还费显存。3.3 训练超参学习率、batch、epoch 的金融场景取值金融语料通常比通用语料小训练轮数不能多否则模型会把问答对背下来而不是学规律。学习率用 1e-4 到 2e-4cosine 调度warmup 比例 0.03。batch 用梯度累积凑到等效 64 到 128。epoch 一般 2 到 3超过 3 轮验证集 loss 就开始回升。# 以常见训练脚本为例参数按金融场景调整 python train.py \ --model_name_or_path /models/llama-7b-chat \ --data_path finance_alpaca.jsonl \ --output_dir ./output_finance_lora \ --num_train_epochs 3 \ --per_device_train_batch_size 4 \ --gradient_accumulation_steps 8 \ --learning_rate 1.5e-4 \ --lr_scheduler_type cosine \ --warmup_ratio 0.03 \ --logging_steps 10 \ --save_steps 200 \ --fp16 Trueper_device_train_batch_size4配合gradient_accumulation_steps8等效 batch 是 32单卡 24GB 能跑。learning_rate1.5e-4是 LoRA 的常用值全量微调要降到 2e-5 量级。save_steps200方便你中途挑 checkpoint金融场景经常是第 2 轮比第 3 轮好别只留最后一个。3.4 训练过程怎么盯loss 曲线与验证集训练时至少盯两个信号训练 loss 和验证 loss。训练 loss 一直降但验证 loss 抬头就是过拟合立刻停。金融问答还要额外看「数字一致性」抽一批含数字的验证样本人工比对输出数字和参考答案模型把 3:1 说成 2:1 这种错误loss 曲线是看不出来的。# 简易验证统计验证集上数字是否一致 import re def num_consistency(pred, ref): p set(re.findall(r\d\.?\d*, pred)) r set(re.findall(r\d\.?\d*, ref)) if not r: return None return len(p r) / len(r) # 低于 0.8 说明模型在编数字需要回查数据或降 epoch这个函数返回预测与参考答案的数字重合率低于 0.8 就要警惕。它不能替代人工评测但能快速筛出「数字幻觉」严重的 checkpoint。4. 推理与部署把微调后的 LLaMA 变成能对外服务的问答接口4.1 推理引擎选型vLLM、llama.cpp 还是原生 transformers微调完只是拿到权重要对外服务还得选推理引擎。常见三类原生 transformers 最简单但吞吐低vLLM 用 PagedAttention吞吐能高几倍适合有 GPU 的服务端llama.cpp 支持 CPU 和量化适合没有 GPU 或要本地部署的场景。金融私有化部署经常是「一台带卡服务器 若干无卡终端」服务端用 vLLM终端走 API。引擎硬件吞吐量化支持适用transformersGPU低有限调试、小流量vLLMGPU高GPTQ/AWQ服务端主力llama.cppCPU/GPU中GGUF 全系本地、边缘选型看两点并发量和是否有卡。并发过 10 就上 vLLM没卡就 llama.cpp 配 Q4 量化7B 模型 Q4 大概 4GB 出头普通机器能跑。4.2 合并 LoRA 权重并启动推理服务LoRA 训练出的是旁路权重部署前要合并回基座否则推理时还得挂 PEFT多一层开销。from peft import PeftModel from transformers import AutoModelForCausalLM, AutoTokenizer base AutoModelForCausalLM.from_pretrained(/models/llama-7b-chat) model PeftModel.from_pretrained(base, ./output_finance_lora) model model.merge_and_unload() # 合并旁路 model.save_pretrained(./merged_finance) tokenizer AutoTokenizer.from_pretrained(/models/llama-7b-chat) tokenizer.save_pretrained(./merged_finance)merge_and_unload把 LoRA 权重加进基座并卸载 PEFT 结构合并后就是一个标准模型目录。注意合并要在 FP16 下做量化后再合并精度会掉。合并完用同样的验证集跑一遍确认效果和合并前一致不一致说明合并过程有问题。4.3 问答接口检索增强与微调模型的配合纯微调模型的知识是「冻结」在权重里的新公告、新规则它不知道。生产环境一般配一层检索用户问题先检索知识库把命中片段塞进input再交给微调模型生成。这样既用上了微调学到的金融口径又保证了知识新鲜度。def answer(question, retriever, model, tokenizer): docs retriever.search(question, top_k3) context \n.join(docs) prompt f参考资料{context}\n问题{question}\n回答 inputs tokenizer(prompt, return_tensorspt).to(model.device) out model.generate(**inputs, max_new_tokens256, temperature0.3, do_sampleFalse) return tokenizer.decode(out[0], skip_special_tokensTrue)top_k3是金融问答的常用值太多会稀释关键信息。temperature0.3加do_sampleFalse让输出稳定金融场景不需要创造性。检索器可以用向量库也可以用关键词加向量混合后者在专有名词多的金融语料上召回更稳。5. 避坑与排查金融微调里最容易翻车的五件事5.1 现象模型回答流畅但数字全错原因训练数据里数字被清洗规则误删或模型在生成时自由发挥。金融问答的数字是硬约束模型没有「必须引用原文数字」的机制。解决在system里加「所有数字必须来自参考资料」训练数据里保留数字上下文推理时用 4.1 节的数字一致性函数做后置校验不一致就拒答或转人工。5.2 现象训练 loss 降到很低但问答答非所问原因数据格式不统一有的样本有input有的没有模型学混了或者 epoch 太多模型把问答对背下来换个问法就崩。解决统一格式input为空时也保留字段把 epoch 降到 2加验证集早停用同义改写做数据增强让模型学语义而不是学字面。5.3 现象合并 LoRA 后效果比合并前差原因合并时精度不对比如基座是 FP16 而合并脚本用了 FP32或者合并顺序搞错。解决合并全程用 FP16合并后立刻用同一批验证样本对比差异超过阈值就回退重做。别在量化模型上合并 LoRA。5.4 现象推理服务并发一高就 OOM原因vLLM 的gpu_memory_utilization设太高或max_model_len开太大KV cache 吃满显存。解决gpu_memory_utilization从 0.9 降到 0.8max_model_len按实际问答长度设金融问答一般 1024 够用别默认开 4096。5.5 现象新公告一问三不知原因微调模型知识冻结训练后新增的语料它没见过。解决上检索增强把新公告进向量库推理时检索注入。微调负责「怎么答」检索负责「答什么」两者分工别混。6. 进阶技巧用评测集把金融问答效果量化住微调做完最怕的是「感觉还行」但说不清好在哪。金融场景必须有一套自己的评测集否则每次改数据、改参数都是玄学调优。我的做法是人工构造 200 到 500 条评测问答覆盖事实查询、数字计算、合规判断、拒答四类每条标注参考答案和关键点。评测指标分三层第一层是关键词命中率看答案有没有覆盖关键点第二层是数字一致性用 3.4 节的函数第三层是拒答准确率专门测模型该说「不知道」时有没有硬编。三层都过才算这个 checkpoint 可用。def eval_sample(pred, ref, keywords): hit sum(1 for k in keywords if k in pred) / len(keywords) num_ok num_consistency(pred, ref) return {keyword_hit: hit, num_consistency: num_ok} # 批量跑评测集按 keyword_hit 排序挑 checkpointkeywords是每条评测样本人工标注的关键点keyword_hit低于 0.6 说明答案跑偏。批量跑完按分数排序别只看 loss 挑模型。我一般会留一个「黄金评测集」不参与任何训练只在最终选型时用避免调参调出过拟合。还有个实用技巧把拒答样本单独加权。金融场景里模型说「这个问题我需要更多信息」比它编一个答案强得多。训练数据里故意放 5% 到 10% 的拒答样本output写「根据现有资料无法确定」能显著降低幻觉率。这个比例别太高否则模型变得过于保守简单问题也拒答。最后说个血泪经验金融微调最贵的不是算力是数据标注和评测的人力。我见过太多团队把预算全砸在卡上数据随便洗洗就开训结果模型答得花里胡哨但没一句能用。先把评测集建起来再回头定数据标准和训练参数顺序反了就是给自己挖坑。希望帮到你。本文还有配套的精品资源点击获取
返回列表