微信扫码
添加专属顾问
我要投稿
实战分享:如何利用昇腾NPU高效微调Qwen3模型,打造量化交易代码生成器。 核心内容: 1. 昇腾910B3环境下的Qwen3模型微调全流程解析 2. 量化因子公式转Python代码的独特数据合成方案 3. 模型部署策略与云端/本地协同计算成本优化方案
前一段时间 Qwen3 发布了,它支持动态推理,而且其小参数量模型也取得了相当优秀的成绩。恰巧参与华为的活动,有昇腾910B3的算力时长资助,这就拿来试试水。
昇腾 910B3(64GB 显存)
昇腾开发包(ascend-toolkit) 8.2.RC1.alpha002
Python 3.10.14
本文将从微调的选题与数据合成讲起,若读者只需昇腾环境下的微调与部署操作,请自行跳至文章后半部分。
选题与
准备
高中时候看过薛兆丰的《经济学讲义》,其中戏称到,计算机同学们都先在 35 岁前完成“资本的原始积累”,然后用原始资金投身到金融领域,跨界转型,叱诧风云。
这就微调一个辅助量化交易的大模型对冲一下程序员的职业风险。
量化交易系统简单来说就是一个用数学、统计和计算机程序来替代人脑,进行自动化投资和交易的系统。
微软在 Github 上有一个开源仓库叫做 RD-Agent ,它把类似量化交易、医学数据分析等的研究系统分为 Research 和 Development,即研究和实验两部分。RD Agent 的 Research 端通过不断地对某个现象提出假设,提出相关的因子分析公式,再由 Development 端去执行和验证因子公式是否有效,实现了对科学问题的研究能力。
RD Agent 在 MLE-Bench 这一检测 Agent 在机器学习工程表现的榜单上,取得了第一的成绩。(此为官方仓库的 README 上宣称,笔者最新看到的是 InternAgent 取得了综合第一的成绩,RD Agent 退居综合第二名。)
可是,如果纯使用云端的模型运行 RD Agent 就成本有点高了,本地部署的话,一般情况又负担不起大参数量的模型,于是我就考虑:Research 端的大模型仍然使用云端 API,以使用 DeepSeek-R1 等大参数量、擅长推理的模型;Development 端的大模型则使用微调后的模型,专注于转化量化因子公式为 Python 代码,以供下游模块的调用。
综上,本次微调的目标是:基于 Qwen3-8B 模型,微调一个将量化因子对应的 Latex 公式转化为 Python 函数的模型。
针对数据集的合成,并未直接使用 RD Agent 进行合成,而是参考了 Camel Agent Datagen 中 Self-Instruct: Instruction Generation 的思路:
下方为单项数据示例,代码部分进行了隐藏以减少文章篇幅:
{"latex_formula": "LiquidityFactor = \\frac{1}{3} \\left( \\frac{Volume_{t}}{AvgVolume_{21}} + \\frac{AmihudRatio_{t}}{AvgAmihud_{21}} + \\frac{BidAskSpread_{t}}{AvgSpread_{21}} \\right)","description": "流动性复合因子通过结合成交量比率、Amihud非流动性比率和买卖价差三个子因子,综合衡量股票的流动性水平。逻辑在于从交易活跃度、价格冲击成本和交易成本三个维度评估流动性。目的是识别流动性好、交易成本低的股票,降低交易摩擦风险。参数包括:当前成交量(Volume_t)、21日平均成交量(AvgVolume_21)、当前Amihud比率(AmihudRatio_t)、21日平均Amihud比率(AvgAmihud_21)、当前买卖价差(BidAskSpread_t)、21日平均买卖价差(AvgSpread_21)。因子值越低表示流动性越好。","code": "import numpy as np\n\ndef calculate_liquidity_factor(\n volume_t: float,\n avg_volume_21: float,\n amihud_ratio_t: float,\n avg_amihud_21: float,\n bid_ask_spread_t: float,\n avg_spread_21: float\n) -> float:..."}
由于我们的任务是让 Qwen3-8B 学会在量化分析这一场景下,通过 latex 公式生成对应的高可用函数,所以我们选择指令微调。指令微调让大模型去学习某一任务的答案生成方式。
写个简单的 Python 脚本即可完成 json 的转化,下方为其中一个转化后的示例数据:
{"instruction": "你现在是量化分析专家,具有出色的编码能力。基于下述信息开发出Latex表示的量化因子公式对应的Python函数,需有完整的函数文档,且考虑边界条件问题。","input": "输入:\n# latex公式\n\\text{Lower Band}_t = \\text{SMA}_t(n) - k \\times \\sigma_t(n) \\\\ \\text{其中:} \\\\ \\text{SMA}_t(n) = \\frac{1}{n} \\sum_{i=0}^{n-1} C_{t-i} \\\\ \\sigma_t(n) = \\sqrt{\\frac{1}{n} \\sum_{i=0}^{n-1} (C_{t-i} - \\text{SMA}_t(n))^2}\n# 描述\n布林带下轨线指标通过计算股价的移动平均和标准差,衡量价格波动下限。逻辑:1) 计算n日收盘价(C)的简单移动平均(SMA);2) 计算同期收盘价的标准差(σ);3) 下轨线=SMA减去k倍标准差。目的:识别超卖区域和价格支撑位,当股价触及下轨时可能预示反弹机会。参数:n=移动平均周期(默认20日),k=标准差乘数(默认2.0)。\n","output": "```python import numpy as np\nfrom typing import Union, Optional\n\n\ndef bollinger_lower_band(prices: Union[list, np.ndarray], \n n: int = 20, \n k: float = 2.0) -> np.ndarray:\n ..."}
至此我们完成了微调数据集的合成,下一步在昇腾 NPU 上完成微调和部署操作。
类似 N 卡下跑 AI 模型需要安装 nvidia 驱动和 cuda toolkit,在昇腾 npu 下跑 AI 模型也需要安装对应驱动和 ascend toolkit 开发包(CANN)。
CANN 是华为针对 AI 场景推出的异构计算架构,对上支持多种 AI 框架,对下服务 AI 处理器与编程,发挥承上启下的关键作用,是提升昇腾 AI 处理器计算效率的关键平台。
由于白嫖的算力环境是一个受限容器,无法进行驱动安装与更改操作,故此部分只提供官方教程作为参考。
请打开昇腾官方网站,根据环境信息下载对应软件包:https://www.hiascend.com/document/detail/zh/canncommercial/80RC2/softwareinst/instg/instg_0001.html
请参考昇腾官网的教程:https://www.hiascend.com/document/detail/zh/canncommercial/80RC2/softwareinst/instg/instg_0003.html
若安装正确,可以使用下述命令获取 CANN 软件包的版本信息:
cd /usr/local/Ascend/ascend-toolkit/latest/{arch}-linuxcat ascend_toolkit_install.info
我这里使用的 CANN 组件版本是 8.2.RC1.alpha002。
此时,你也应当可以使用 npu-smi info 查看当前昇腾 NPU 的状态信息。
我们将使用上述两个框架完成对 Qwen3-8B 的微调操作。
相关官方教程,可供附加参考: LLaMA Factory 在昇腾 NPU 下的官方教程:https://llamafactory.readthedocs.io/zh-cn/latest/advanced/npu.html
LLaMA Factory+ 昇腾 NPU 全流程实践教程:https://ascend.github.io/docs/sources/llamafactory/example.html
# 务必按顺序执行下述命令pip uninstall te topi hccl -y # 卸载可能装过的包,确保环境正确pip install sympy # SymPy 符号计算# 下面两个whl文件,根据实际情况来配置版本号pip install /usr/local/Ascend/ascend-toolkit/latest/lib64/te-*-py3-none-any.whl # Tensor Engine (TE) 算子开发库pip install /usr/local/Ascend/ascend-toolkit/latest/lib64/hccl-*-py3-none-any.whl # HCCL(Huawei Collective Communication Library)通信库
# 克隆并安装LLaMA Factorygit clone --depth **1** https://github.com/hiyouga/LLaMA-Factory.gitcd LLaMA-Factorypip install -e ".[torch-npu,metrics,swanlab]"# 下述命令在安装后执行# 初始化昇腾NPU的相关环境变量source /usr/local/Ascend/ascend-toolkit/set_env.sh# 使用modelscope来下载模型权重文件export USE_MODELSCOPE_HUB=1
llamafactory-cli env
- `llamafactory` version: **0**.8.2.dev0- Platform: Linux-4.19.90-vhulk2211.3.0.h1543.eulerosv2r10.aarch64-aarch64-with-glibc2.31- Python version: **3**.10.14- PyTorch version: **2**.1.0 **(**NPU**)**- Transformers version: **4**.41.2- Datasets version: **2**.19.2- Accelerate version: **0**.31.0- PEFT version: **0**.11.1- TRL version: **0**.9.4- NPU type: xxx- CANN version: **8**.0.RC2.alpha001
到这里一步环境已经配好,可以运行命令,使用比较方便的 webui 配置微调参数:
llamafactory-cli webui
可以使用 ssh 的端口转发,以通过 http://localhost:7860 访问服务器上的该服务。
打开后便可以看到如下配置界面,其中可选择语言为 zh,模型选择 Qwen3-8B-Thinking,对应在 ModelScope 的模型名是 Qwen/Qwen3-8B,对话模板为 qwen3_nothink,微调方法为 Lora 微调,共训练 15 轮次,学习率为 5e-5。
需要特别注意的是,要选择 Qwen3-8B-Thinking 模型,而不是 Qwen3-8B-Base 模型。
“Base” 模型是大语言模型最原始的形态,通常是经过海量文本数据训练的无监督模型。这类模型通过自回归的方式预测下一个词,从而具备强大的语言生成能力。这类模型的目标是捕捉语言的结构、语法以及广泛的上下文语义,但它并没有特定的任务导向。
在下方可以展开 Swanlab参数设置 ,使用 Swanlab 可以便捷地对大模型微调进行跟踪、记录与可视化。注意要勾选 使用Swanlab 并填入项目名与密钥,便于同步到云端的训练看板。
其余参数配置完善后,点击开始,便可以在昇腾 NPU 上对 Qwen3-8B 进行 Lora 微调。
我的微调测试看板结果如下,可以看到 loss 逐渐下降并趋于平衡:
在 Swanlab 的系统图表栏内,也可以直观看到昇腾 NPU 确实在发力。
此时,你可以在 llamafactory webui 的 chat 栏加载微调后的模型并测试,此处不再演示,直接借助下文的部署进行测试。
Lora 微调后的产物是新增的 Lora 权重层,此时是需要原始模型权重文件 +Lora 权重文件才可以运行的,也可以选择合并至原模型,输出完整的微调后的 Qwen3-8B 模型权重文件。
需要注意把下方命令中的参数改为你实际环境下的参数。
ASCEND_RT_VISIBLE_DEVICES=0 llamafactory-cli export \--model_name_or_path qwen/Qwen3-8B \--adapter_name_or_path ./saves/Qwen3-8B-Thinking/lora/train_2025-09-26-15-12-36/ \--template qwen3 \--finetuning_type lora \--export_dir ./saves/Qwen3-8B/lora/megred-model-path \--export_size 5 \--export_device auto \--export_legacy_format False
MindNLP 是基于 MindSpore 的一个自然语言处理(NLP)开源库,其中包含了许多自然语言处理的常用方法,提供了一个易用的 NLP 平台,旨在帮助研究人员和开发者更高效地构建和训练模型。
在部署时,您可以选择 vllm 或者其他框架,此处为了多尝试下,选择了华为的 mindnlp 框架完成部署测试工作,尝试一下华为昇思提供的框架。
此处建议新建一个 Python 虚拟环境,mindnlp 与 LLaMA Factory 存在部分依赖冲突问题。
# 对应Python版本3.10 CANN软件包版本8.2.RC1.alpha002pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simplepip install modelscopegit clone https://gitee.com/mindspore-lab/mindnlp.gitpip install "peft==0.17.1" "accelerate ==1.10.1" "transformers==4.55.4"cd mindnlpgit checkout 6719e5e60e72df9a1c7b9473029c7ccf62ff8a12scbash scripts/build_and_reinstall.shpip install decorator gradio
error: invalid command 'bdist_wheel' 则执行下述命令,以更新到新的打包工具:pip install wheelpip install --upgrade setuptools
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.te 0.4.0 requires cloudpickle, which is not installed.te 0.4.0 requires decorator, which is not installed.te 0.4.0 requires ml-dtypes, which is not installed.te 0.4.0 requires tornado, which is not installed.schedule-search 0.0.1 requires absl-py, which is not installed.schedule-search 0.0.1 requires decorator, which is not installed.opc-tool 0.1.0 requires decorator, which is not installed.op-compile-tool 0.1.0 requires getopt, which is not installed.op-compile-tool 0.1.0 requires inspect, which is not installed.op-compile-tool 0.1.0 requires multiprocessing, which is not installed.auto-tune 0.1.0 requires decorator, which is not installed.
# 按顺序执行pip uninstall te topi hccl -y # 卸载可能装过的包,确保环境正确pip install sympy # SymPy 符号计算# 下面两个whl文件,根据实际情况来配置版本号pip install /usr/local/Ascend/ascend-toolkit/latest/lib64/te-*-py3-none-any.whl # Tensor Engine (TE) 算子开发库pip install /usr/local/Ascend/ascend-toolkit/latest/lib64/hccl-*-py3-none-any.whl # HCCL(Huawei Collective Communication Library)通信库
source /usr/local/Ascend/ascend-toolkit/set_env.sh
python -c "import mindspore;mindspore.set_device('Ascend');mindspore.run_check()"
MindSpore version: 版本号The result of multiplication calculation is correct, MindSpore has been installed on platform [Ascend] successfully!
为了直观方便,我们选择使用 Gradio 来构建测试界面。
# run_qwen3.pyimport mindsporefrom mindnlp import corefrom transformers import AutoTokenizer, AutoModelForCausalLM, TextIteratorStreamerimport gradio as grimport osimport timefrom threading import Thread# --- 配置区域 ---# 1. 模型路径:请确保该路径下包含模型文件和配置文件MODEL_PATH = 'output/qwen3_8b_lora' # 更改为实际导出的模型路径# 2. System Prompt:定义模型的角色和行为,可以根据需要修改SYSTEM_PROMPT = "【系统提示词】"# 3. Gradio 界面文本:可以根据需要修改界面上的介绍和样例GRADIO_TITLE = ""GRADIO_EXAMPLES = ["样例1", "样例2", "样例3"]# --- 1. 模型一次性加载 ---# 模型和分词器被加载到内存中,供后续所有推理请求复用。print("="*80)print("正在加载模型和分词器,此过程可能需要几分钟,请耐心等待...")start_time = time.time()# 检查模型路径是否存在,提供更友好的错误提示if not os.path.exists(MODEL_PATH):raise FileNotFoundError(f"错误:模型路径 '{MODEL_PATH}' 不存在。请检查路径是否正确。")try:# 加载分词器tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH,use_fast=False,trust_remote_code=True)# 加载模型model = AutoModelForCausalLM.from_pretrained(MODEL_PATH,ms_dtype=mindspore.bfloat16,device_map=0)# 将模型移动到 NPU 上model = model.npu() # type: ignoreend_time = time.time()print(f"模型加载成功!耗时: {end_time - start_time:.2f} 秒。")# --- 模型预热 ---print("="*80)print("正在进行模型预热,首次推理编译可能需要一些时间...")warmup_start_time = time.time()try:# 构造一个虚拟的输入,内容不重要,但格式要对warmup_text = "这是一个预热测试"warmup_conversation = [{"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": warmup_text}]inputs = tokenizer.apply_chat_template(warmup_conversation,add_generation_prompt=True,tokenize=True,return_tensors="ms",return_dict=True,enable_thinking=False).to('cuda')# 执行一次简短的生成,触发编译_ = model.generate(inputs['input_ids'], max_length=64)warmup_end_time = time.time()print(f"模型预热完成!耗时: {warmup_end_time - warmup_start_time:.2f} 秒。")except Exception as e:print(f"模型预热失败: {e}")print("="*80)print("Gradio 服务即将启动...")print("="*80)except Exception as e:print(f"加载模型时发生错误: {e}")# 如果模型加载失败,则退出程序exit()# --- 2. 定义推理函数 ---def predict(message: str, history: list = []):"""接收用户输入的需求,使用预加载的模型进行分析并返回结果。"""# 对空输入进行处理if not message.strip():return "⚠️ 输入不能为空,请输入您的需求描述。"# 构建聊天模板conversation = [{"role": "system", "content": SYSTEM_PROMPT}] + [{"role": msg["role"], "content": msg["content"]}for msg in history] + [{"role": "user", "content": message}]inputs = tokenizer.apply_chat_template(conversation,add_generation_prompt=True,tokenize=True,return_tensors="ms",return_dict=True,enable_thinking=False # 此处关闭了深度思考).to('cuda')print(f"输入的 token 数量: {inputs['input_ids'].shape[1]}, 内容: {inputs}")# 定义生成参数gen_kwargs = {"max_length": 4096, "do_sample": True, "top_k": 1}# 执行推理with core.no_grad():outputs = model.generate(**inputs, **gen_kwargs)print(f"响应生成完毕, 共生成 {outputs.shape[1]} 个 token。")outputs = outputs[:, inputs['input_ids'].shape[1]:]response = tokenizer.decode(outputs[0], skip_special_tokens=True)print(f"模型响应: {response}")return response# --- 3. 创建并启动 Gradio 界面 ---with gr.Blocks() as demo:gr.Markdown(GRADIO_TITLE)chatbot = gr.Chatbot(value=[],elem_id="chatbot",label="对话窗口",bubble_full_width=False,height=600)# 将 ChatInterface 的 fn 指向我们新的流式函数 predict_streaminggr.ChatInterface(fn=predict,chatbot=chatbot,examples=GRADIO_EXAMPLES,title=None,description=None,textbox=gr.Textbox(placeholder="请在这里输入您的需求...", container=False, scale=7),submit_btn="🚀 发送",type="messages",save_history=True,)demo.launch(server_name="0.0.0.0")
使用 python run_qwen3.py 即可完成部署工作,此处仍然需要配置本地 7860 的端口转发服务。
如图为微调后的 Latex 公式 Coder 模型(关闭深度思考)。
此处为从阿里云百炼平台调用的微调前的 Qwen3-8B 模型(此处被强制深度思考了)。
如何评估模型的效果呢?实际上我们又写了一套脚本,输入模型没见过的量化因子公式,让大模型返回对应的 Python 函数,并由 Deepseek R1 针对代码的完整性、正确性、合理性、健壮性进行量化打分,人工监督打分环节,形成打分表。
举个例子来看,我们手动给 R1 输入上面提到的 EPS 复合因子任务要求以及两个版本的输出结果,由 R1 做出点评:
从 R1 的角度来说,第一个实现即微调后的模型,其输出的代码更为合理规范,符合我们微调的目的。
实际上,执行完 50 个量化因子公式的跑分后,微调后比微调前的 Qwen3-8B 高出了 20 分,此次微调是比较成功的。
第一次微调 8B 参数量的模型 + 第一次使用昇腾 NPU 微调模型,这一经历暂时告一段落。
这次确实过了把微调瘾,值得注意的是,不论什么硬件环境下进行 AI 模型训练与部署,他们的架构思路是相似的,所需执行的环境安装与部署流程也是相似的,如上文提到的 ascend toolkit 之于昇腾 NPU,就如 cuda toolkit 之于 Nvidia 显卡,所以不论什么环境总有一些需要关注的共同问题。避免每次掉入相似的坑里,还是得举一反三这些问题。
在 Lora 微调时,也需要注意,Lora 秩越大/batch_size 越大/量化精度越高,是需要更高的显存占用的。最开始我选择了昇腾 910B1 环境,结果它的 32GB 显存爆了。但是借着能坐豪车不坐三蹦子的原则,不降超参数情况下,我改为了昇腾 910B3,拥有 64GB 显存的卡。在实际过程中,如果无法升级算力资源,还是需要考虑降低量化精度、减小 batch_size 等来减少对显存的需求。
在此也十分感谢华为提供的昇腾算力资源。
这是因为缺少 wheel 打包工具或者当前的 python 打包工具版本低,执行下述命令即可:
pip install wheelpip install --upgrade setuptools
错误类似下方:
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.te 0.4.0 requires cloudpickle, which is not installed.te 0.4.0 requires decorator, which is not installed.te 0.4.0 requires ml-dtypes, which is not installed.te 0.4.0 requires tornado, which is not installed.schedule-search 0.0.1 requires absl-py, which is not installed.schedule-search 0.0.1 requires decorator, which is not installed.opc-tool 0.1.0 requires decorator, which is not installed.op-compile-tool 0.1.0 requires getopt, which is not installed.op-compile-tool 0.1.0 requires inspect, which is not installed.op-compile-tool 0.1.0 requires multiprocessing, which is not installed.auto-tune 0.1.0 requires decorator, which is not installed.
/usr/local/Ascend/ascend-toolkit/latest/lib64/ 下是否有一堆 whl 包:ls /usr/local/Ascend/ascend-toolkit/latest/lib64 | grep whl
auto_deploy_utils-0.1.0-py3-none-any.whlauto_tune-0.1.0-py3-none-any.whldataflow-0.0.1-py3-none-any.whlhccl-0.1.0-py3-none-any.whlllm_datadist-0.0.1-py3-none-any.whlop_compile_tool-0.1.0-py3-none-any.whlopc_tool-0.1.0-py3-none-any.whlschedule_search-0.1.0-py3-none-any.whlte-0.4.0-py3-none-any.whl
# 按顺序执行pip uninstall te topi hccl -y # 卸载可能装过的包,确保环境正确pip install sympy # SymPy 符号计算# 下面两个whl文件,根据实际情况来配置版本号pip install /usr/local/Ascend/ascend-toolkit/latest/lib64/te-*-py3-none-any.whl # Tensor Engine (TE) 算子开发库pip install /usr/local/Ascend/ascend-toolkit/latest/lib64/hccl-*-py3-none-any.whl # HCCL(Huawei Collective Communication Library)通信库
如果过程中又出现了缺少某某包,只要不在这个本地文件夹下,则尝试 pip install 从云端安装,然后再执行失败的命令。
再次审查上文安装步骤,并判断当前环境是否正确安装。
source /usr/local/Ascend/ascend-toolkit/set_env.s
该环境变量指明了 CANN 中的相关可执行文件路径。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2025-11-05
2张4090竟能本地微调万亿参数Kimi K2!趋境联合清华北航把算力门槛击穿了
2025-10-21
从零教你微调一个专属领域大模型,看完小白也能学会炼丹!(完整版)
2025-10-14
用Macbook微调Qwen3!手把手教你用微调给Qwen起一个新名字
2025-10-12
微调已死?Google 和斯坦福论文指出AI 学习新范式
2025-09-25
如何将 AI 代码采纳率从30%提升到80%?
2025-09-24
一位淘宝工程同学的大模型LoRA微调尝试
2025-09-20
在Colab中微调Qwen3-4B模型实战指南
2025-09-09
微调Qwen2.5模型的完整指南
2025-08-25
2025-10-12
2025-08-23
2025-08-11
2025-10-14
2025-09-07
2025-09-04
2025-09-09
2025-08-18
2025-09-20