ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

大模型领域适应自动化:从LoRA到AutoAdapt的技术实践

2026/8/2 18:20:55 拓冰建站 浏览量
大模型领域适应自动化:从LoRA到AutoAdapt的技术实践

1. 项目概述:当大模型遇上“水土不服”

最近在折腾几个开源大模型,想让它帮我处理一些特定领域的文档,比如医疗报告或者法律合同。结果发现,直接拿通用模型去用,效果简直惨不忍睹——要么是专业术语理解偏差,要么是生成的回复过于“通用”,缺乏领域深度。这其实就是典型的“水土不服”问题。大语言模型(LLM)在通用语料上训练得再好,面对一个全新的、数据分布迥异的专业领域时,其表现也会大打折扣。这个过程,在学术和工业界被称为“领域适应”。

传统的领域适应方法,无论是全参数微调,还是更轻量的LoRA、QLoRA,都离不开一个核心环节:人工介入。你需要收集高质量的领域数据,清洗、标注,然后设计训练流程,调整超参数,最后评估效果。整个过程耗时耗力,对从业者的经验和算力资源都是不小的考验。有没有一种方法,能让这个过程更“智能”一点,甚至自动化起来?这正是“AutoAdapt: Automated domain adaptation for large language models”这个项目标题所指向的核心愿景。它探讨的,是如何构建一套系统或框架,将领域适应的关键步骤——从数据发现、处理,到模型适配策略选择、训练执行,再到效果评估与迭代——尽可能地自动化,降低技术门槛,提升效率。

简单来说,AutoAdapt想解决的是“如何让大模型快速、低成本地适应一个新领域”这个痛点。它不仅仅是一个工具,更代表了一种方法论:将人的经验沉淀为可复用的自动化流程。这对于中小企业、独立开发者,或者任何希望快速验证大模型在垂直场景应用价值的团队来说,意义重大。你不再需要组建一个庞大的算法团队,可能只需要提供一些种子数据或领域描述,剩下的脏活累活,交给自动化流程去尝试和优化。

2. 领域适应的核心挑战与自动化切入点

要实现自动化,首先得明白手动做领域适应时,我们到底在对付哪些“麻烦事”。只有拆解了这些挑战,才能找到自动化的突破口。

2.1 数据层面的“脏、乱、少”

领域适应的基石是数据,而领域数据往往存在三大难题:

  1. 数据质量堪忧(脏):从网络爬取或内部系统导出的文本,充斥着广告、无关链接、格式错乱、重复内容。自动化系统需要能识别并过滤这些噪声。
  2. 数据结构混乱(乱):数据可能以PDF、扫描图片、数据库字段、JSON日志等多种形态存在。自动化流程需要集成OCR、格式解析、信息抽取等模块,将非结构化或半结构化数据转化为干净的纯文本。
  3. 高质量标注数据稀缺(少):监督微调需要指令-回答对。在专业领域,构造这样的数据成本极高。自动化系统可能需要利用“自指令生成”技术,或者采用基于检索增强生成(RAG)的轻量化适配方案来绕过对大量标注数据的依赖。

自动化切入点:构建一个智能的数据处理流水线。这个流水线可以自动识别数据源类型,调用相应的解析器(如pypdfpdfplumber处理PDF,pytesseract处理图片),然后经过去重、去噪、文本规范化等步骤。更进一步,可以利用一个较小的、经过初步领域适应的LLM,来自动生成符合领域风格的指令-回答对,为后续的监督微调创造训练数据。

2.2 适配策略的“选择困难症”

面对一个待适应的模型和一份领域数据,应该选择哪种适配策略?全量微调效果最好但成本最高;LoRA参数高效但可能无法捕捉领域全部特性;Prompt Tuning或Prefix Tuning几乎不增参数,但效果上限可能较低。此外,学习率、训练轮次、批次大小等超参数如何设置?

自动化切入点:构建一个“策略选择与超参数优化”引擎。这个引擎可以基于一些元特征自动决策,例如:

  • 数据量:数据极少(<1000条)时,优先推荐RAG或Prompt Tuning;数据充足时,可以考虑LoRA甚至全量微调。
  • 领域与通用领域差异度:可以通过计算领域文本与通用语料在嵌入空间的平均余弦距离来粗略估计。差异越大,可能越需要更深度的适配(如LoRA)。
  • 计算预算与时间约束:明确给出GPU内存、训练时间限制,引擎自动排除不满足条件的策略。

然后,可以采用基于贝叶斯优化或多臂老虎机(Multi-armed Bandit)的自动化超参数调优(AutoML)技术,在给定的策略空间和资源约束下,寻找相对最优的配置组合。

2.3 评估与迭代的“黑盒”困境

模型适配后,效果到底怎么样?在通用基准(如MMLU)上的分数可能无法反映其领域能力。我们需要领域特定的评估集。但构建这样的评估集本身又是一个费时费力的过程。

自动化切入点:自动化评估体系。这包括两个层面:

  1. 自动构建测试集:从预留的领域数据中,通过聚类、关键词提取等方式,自动筛选出一批具有代表性的问题。甚至可以结合大模型自身(如GPT-4),根据领域文档自动生成相关的问答对作为“银标准”测试集。
  2. 自动化评估指标:除了传统的困惑度(PPL),更需要自动化计算领域相关的指标。例如,利用一个经过验证的领域实体识别模型,检查生成文本中领域实体的准确率;或者计算生成文本与领域参考文本在语义嵌入上的相似度。自动化系统需要能够运行这些评估流水线,并生成综合报告。

2.4 持续学习的“冷启动”问题

领域知识是不断更新的。当有新数据到来时,是重新训练一个模型,还是在原有适配模型上继续微调?如何避免灾难性遗忘?

自动化切入点:设计自动化的持续学习(Continual Learning)触发与调度机制。系统可以监控新流入数据的分布变化,当检测到显著偏移(Drift Detection)时,自动触发一轮轻量级的增量适配流程。同时,可以集成弹性权重巩固(EWC)或梯度情景记忆(GEM)等算法,来自动化地缓解对旧知识的遗忘。

3. 构建AutoAdapt系统的技术架构设想

基于以上挑战与切入点,我们可以勾勒出一个AutoAdapt系统可能的技术架构。这个架构不是某个具体项目的实现,而是基于当前技术趋势的一个合理推演。

3.1 核心模块分解

一个完整的AutoAdapt系统可能包含以下五个核心模块,它们以流水线或协同的方式工作:

模块名称核心职责关键技术/组件
数据感知与预处理模块自动发现、获取、清洗、格式化领域数据。网络爬虫(Scrapy)、文档解析库(unstructured)、去重算法(SimHash)、文本规范化工具。
适配策略决策引擎分析数据与资源约束,推荐适配策略与初始超参数。元学习(Meta-Learning)模型、轻量级特征提取器、策略收益预测器。
自动化训练执行器根据决策引擎的输出,配置并运行训练任务,管理资源。训练框架封装(Hugging Face Transformers, PEFT)、任务队列(Celery)、资源管理器(Kubernetes)。
自动化评估与验证模块自动构建测试集,运行多维评估,判断适配是否达标。测试集生成(LLM-as-a-Judge)、评估指标计算(Rouge, BLEU, 嵌入相似度)、基准模型对比。
模型管理与部署模块版本管理、效果追踪、模型打包与一键部署。模型注册中心(MLflow)、API服务框架(FastAPI)、监控仪表盘(Grafana)。

3.2 工作流推演

假设我们想让一个LLM适应“智能客服”领域,系统的工作流可能如下:

  1. 输入与初始化:用户提供种子信息,如“智能客服对话”、“产品手册PDF”、“历史工单数据”的存放路径或关键词。系统初始化,设定计算预算(如:单卡A100,训练时间<24小时)。
  2. 数据自动化处理
    • 系统爬取与“智能客服”相关的公开问答数据。
    • 自动解析用户提供的PDF手册和历史工单(可能是CSV格式),将其转换为统一格式的文本。
    • 执行去重、过滤无关文本(如页眉页脚)、按主题或对话轮次进行切分。
    • 利用一个通用LLM,对清洗后的文本进行“指令-回答对”的数据增强。例如,从产品手册中抽出一段描述,让LLM生成“用户可能如何提问”以及“客服应如何回答”。
  3. 策略决策
    • 系统分析处理后的数据:总量约5万对,文本较短,领域术语明确。
    • 结合计算预算,决策引擎判断:数据量中等,领域性较强,但预算有限。推荐策略:采用QLoRA(4-bit量化的LoRA),在基础模型(如ChatGLM3-6B)的注意力模块进行适配。同时,贝叶斯优化器给出初始超参数:学习率=3e-4,秩r=16,alpha=32。
  4. 自动化训练与监控
    • 训练执行器根据策略配置,自动拉取基础模型,加载PEFT库,注入QLoRA适配器,开始训练。
    • 系统实时监控训练损失、GPU利用率,并每隔一定步数在预留的验证集上计算困惑度。
    • 如果检测到损失异常(如NaN)或验证集性能持续下降,自动触发早停(Early Stopping)或学习率衰减。
  5. 自动化评估
    • 训练结束后,评估模块启动。它从预留数据中自动生成100个典型的客服问题作为测试集。
    • 让适配后的模型和原始基础模型同时回答这些问题。
    • 自动计算多项指标:回答的流畅度(困惑度)、与标准答案的相似度(Rouge-L)、是否包含关键产品术语(通过关键词匹配)、以及使用GPT-4作为裁判进行人工偏好模拟评分。
    • 生成对比报告:新模型在领域相关指标上提升30%,但在通用知识问答上略有下降(可接受)。
  6. 部署与反馈
    • 模型管理模块将效果达标的模型打包,并部署为RESTful API服务。
    • 系统提供监控接口,可以收集线上真实用户的反馈(如点赞/点踩)。负面反馈达到一定阈值,可触发新一轮的自动化适应循环。

3.3 关键技术选型与考量

在构建这样一个系统时,一些关键的技术选型需要仔细考量:

  • 基础模型选择:自动化系统需要支持主流开源模型(LLaMA、ChatGLM、Qwen、Baichuan等)。一个可行的方法是维护一个模型仓库,根据用户对中英文、代码能力、上下文长度等需求,自动推荐合适的基础模型。对于自动化流程,模型结构的稳定性(如Transformer层命名规范)非常重要,这影响到LoRA等技术的自动注入。
  • 训练框架:Hugging Face的Transformers+PEFT(Parameter-Efficient Fine-Tuning) 库几乎是当前的标准选择。它们提供了统一的接口,便于自动化脚本操作。Accelerate库可以简化分布式训练配置,适合自动化资源调度。
  • 超参数优化(HPO):对于自动化系统,效率至关重要。网格搜索(Grid Search)太慢,随机搜索(Random Search)效率一般。贝叶斯优化(Bayesian Optimization)是更优的选择,它通过构建代理模型(如高斯过程)来预测不同超参数组合的效果,从而用更少的试验次数找到较优解。像OptunaRay Tune这样的库提供了现成的、可扩展的贝叶斯优化实现。
  • 评估的自动化:这是最具挑战的一环。除了传统指标,引入LLM-as-a-Judge(使用一个更强的LLM,如GPT-4,来评估输出质量)是当前的研究热点。在自动化系统中,可以将其作为一个可选的、但成本较高的评估维度。系统需要设计一套触发逻辑,例如,当传统指标无法明确区分时,再调用GPT-4进行裁判。

注意:完全依赖GPT-4等闭源模型进行自动化评估,会引入API成本、延迟和可控性风险。一个更稳健的方案是结合多种轻量级指标(如基于BERT的语义相似度)和少量人工审核样本,形成综合判断。

4. 实战推演:从零设计一个简易AutoAdapt原型

理论说再多,不如动手画个草图。我们不来虚的,直接设想如何用现有的开源工具,搭建一个最小可行产品(MVP)级别的AutoAdapt原型。这个原型不会面面俱到,但能验证核心自动化流程的可行性。

4.1 定义MVP的目标与边界

我们的MVP目标很明确:给定一个领域文本文件夹和一个基础模型名称,系统能自动完成数据预处理、QLoRA微调、基础评估,并输出适配后的模型。

边界限定

  • 输入:一个包含.txt,.pdf,.md文件的文件夹路径;一个Hugging Face模型ID(如meta-llama/Llama-2-7b-chat-hf)。
  • 输出:适配后的模型文件(包含LoRA权重)和一份简单的评估报告。
  • 策略固定:为了简化,我们固定使用QLoRA(4-bit量化)作为适配方法,只自动化超参数中的学习率。
  • 评估简化:使用训练过程中的验证集损失和困惑度作为主要评估指标,外加一个简单的“领域词频对比”检查。

4.2 技术栈选择

  • 编程语言:Python,生态丰富。
  • 核心库
    • transformers&peft:用于模型加载与QLoRA微调。
    • bitsandbytes:实现4-bit量化。
    • accelerate:简化训练循环。
    • langchain/unstructured:用于文档加载与文本分割。
    • optuna:用于自动化超参数优化(学习率)。
    • scikit-learn:用于简单的文本特征提取(TF-IDF)以辅助评估。
  • 任务编排:使用Python脚本按顺序调用各个模块,暂不引入复杂的任务队列。

4.3 核心代码逻辑拆解

整个原型可以封装在一个Python类中,比如叫SimpleAutoAdapt。以下是其核心方法的逻辑:

1. 数据加载与预处理 (_load_and_chunk_data)

from langchain.document_loaders import DirectoryLoader, UnstructuredFileLoader from langchain.text_splitter import RecursiveCharacterTextSplitter def _load_and_chunk_data(self, data_dir): """加载目录下所有文件,并按固定长度切分文本块。""" # 使用通配符加载所有支持的文件 loader = DirectoryLoader(data_dir, glob="**/*.txt", loader_cls=UnstructuredFileLoader) # 可以扩展支持更多文件类型 # loader = DirectoryLoader(data_dir, glob="**/*.pdf", loader_cls=PyPDFLoader) documents = loader.load() # 使用递归字符分割器,尽量按段落、句子保持语义完整性 text_splitter = RecursiveCharacterTextSplitter( chunk_size=512, # 根据模型上下文长度调整 chunk_overlap=50, separators=["\n\n", "\n", "。", "?", "!", " ", ""] ) chunks = text_splitter.split_documents(documents) # 提取纯文本 texts = [chunk.page_content for chunk in chunks] return texts

这个函数负责把杂乱的文档变成一段段适合模型“消化”的文本块。chunk_size是关键参数,需要匹配基础模型的上下文窗口。unstructured库能处理多种格式,但实际部署中可能需要针对复杂PDF或图片做额外处理。

2. 构建训练数据 (_prepare_train_data)对于无监督的领域适应(如继续预训练),我们可以直接使用这些文本块。对于指令微调,则需要构造指令-回答对。在MVP中,我们可以采用一种简单的“自监督”方式:将文本块作为“回答”,并让模型学习预测下一个词。或者,我们可以假设用户提供的数据已经是整理好的对话格式(如JSONL),这里我们按前者处理。

3. 超参数自动优化 (_auto_tune_lr)我们固定其他参数,只优化学习率。使用Optuna框架:

import optuna import torch from transformers import Trainer, TrainingArguments def _objective(self, trial, train_dataset, eval_dataset, model, tokenizer): """Optuna优化的目标函数:最小化验证集损失。""" # 让Optuna在指定范围内建议一个学习率 lr = trial.suggest_float("learning_rate", 1e-5, 5e-4, log=True) training_args = TrainingArguments( output_dir="./tmp_lora", per_device_train_batch_size=4, gradient_accumulation_steps=4, num_train_epochs=3, # MVP中固定轮次 logging_steps=10, save_steps=100, evaluation_strategy="steps", eval_steps=100, learning_rate=lr, # ... 其他固定参数 ) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, tokenizer=tokenizer, ) trainer.train() # 返回最终验证集损失,Optuna会尝试最小化这个值 eval_results = trainer.evaluate() return eval_results["eval_loss"] def _auto_tune_lr(self, model, tokenizer, train_dataset, eval_dataset): """运行Optuna研究,寻找最佳学习率。""" study = optuna.create_study(direction="minimize") # 将目标函数和参数部分绑定 objective_with_args = lambda trial: self._objective(trial, train_dataset, eval_dataset, model, tokenizer) study.optimize(objective_with_args, n_trials=5) # 进行5次试验 best_lr = study.best_params["learning_rate"] print(f"最佳学习率: {best_lr}") return best_lr

这个过程会尝试5组不同的学习率,最终选出在验证集上损失最小的那个。n_trials可以根据时间和计算资源调整。

4. 执行训练与评估 (run)这是主流程:

def run(self, model_name, data_dir): print("1. 加载并预处理数据...") texts = self._load_and_chunk_data(data_dir) # 对texts进行tokenization,构建dataset... print("2. 加载基础模型和tokenizer...") model, tokenizer = self._load_base_model(model_name) print("3. 配置QLoRA...") model = self._setup_peft_model(model) # 内部调用peft.get_peft_model print("4. 自动优化学习率...") best_lr = self._auto_tune_lr(model, tokenizer, train_dataset, eval_dataset) print("5. 使用最佳学习率进行最终训练...") final_training_args = TrainingArguments(learning_rate=best_lr, ...) trainer = Trainer(...) trainer.train() print("6. 简单领域评估...") self._simple_domain_evaluation(model, tokenizer, texts) print("7. 保存模型...") trainer.model.save_pretrained("./adapted_model")

_simple_domain_evaluation函数可以做一个简单的检查:从领域文本中提取高频词(去除停用词),然后让原始模型和适配后的模型分别生成一段文本,统计这些领域高频词在生成文本中出现的频率。适配后的模型,其领域词频应该显著提高。

4.4 MVP的局限性与扩展方向

这个原型极其简陋,但它验证了“数据自动处理 -> 超参自动调优 -> 训练与评估”的核心闭环。它的局限性很明显:

  • 策略单一:只用了QLoRA。
  • 评估薄弱:仅依赖损失和简单词频。
  • 无智能数据构造:假设数据是纯文本,未处理指令对。
  • 资源管理简单:没有考虑多GPU、任务排队等。

扩展方向

  1. 策略池:将策略决策模块化,支持LoRA、Prefix Tuning、Adapter等多种方法,并根据数据量自动选择。
  2. 智能数据构造:集成一个轻量级LLM(如Phi-3-mini),用于从领域文本中生成指令-回答对。
  3. 强化评估:集成lm-evaluation-harness,自动运行MMLU、CEval等基准测试的一部分子集,并计算领域特定任务的指标。
  4. 流水线化与可视化:使用PrefectAirflow编排任务,并用GradioStreamlit构建一个简单的Web界面,让用户上传数据、选择配置、查看训练过程和评估报告。

5. 避坑指南:自动化过程中的常见陷阱与应对策略

即使有了自动化框架,在实际操作中依然会踩到很多坑。这些坑往往源于对自动化过程过于乐观的估计。下面分享几个我预见到或在实际类似项目中遇到的关键陷阱。

5.1 数据质量导致的“垃圾进,垃圾出”自动化放大

这是最致命的问题。自动化系统如果缺乏有效的数据质量关卡,会虔诚地学习你数据中的所有噪声和偏见。

  • 陷阱表现:模型训练顺利,损失下降,但生成的内容包含大量无关信息、格式错误甚至事实性错误。例如,从爬取的网页数据中,模型学会了生成“点击查看更多”这样的垃圾尾部内容。
  • 应对策略
    • 设置多重过滤器:在预处理流水线中,必须集成基于规则和基于模型的过滤器。规则过滤器可以过滤掉过短/过长文本、包含大量特殊字符或链接的文本。基于模型的过滤器可以使用一个训练好的文本分类模型(如fasttext)来识别并过滤低质量内容(如广告、导航栏文本)。
    • 强化去重:不仅仅是字符级别的去重,更要做语义去重。对于领域数据,同一事实可能被不同文档反复陈述。使用SimHash或MinHash进行粗去重后,再用句子嵌入模型(如all-MiniLM-L6-v2)计算语义相似度,去除高度相似的段落。
    • 人工审核抽样:在自动化流程中设置“检查点”。在数据清洗后,随机采样100-200条数据,自动生成一个预览文件供人工快速浏览。虽然不完全自动化,但这步“人工确认”能极大降低风险。

5.2 超参数搜索的“维数灾难”与成本失控

自动化超参数优化(HPO)听起来很美,但搜索空间一旦稍大,所需的计算成本会呈指数级增长。

  • 陷阱表现:你设置了学习率、批次大小、LoRA的秩(r)和alpha、训练轮次等多个参数进行联合优化。Optuna运行了50个试验,花了三天时间,结果发现最佳配置和默认配置差距不大,投入产出比极低。
  • 应对策略
    • 分阶段优化:不要一开始就进行全参数联合搜索。采用“先粗后精”的策略:
      1. 第一阶段(粗调):固定大部分参数(如使用常用推荐值),只优化最重要的1-2个参数,如学习率。用较少的试验次数(如10次)快速定位大致范围。
      2. 第二阶段(精调):在粗调确定的最佳点附近,再引入其他参数(如批次大小、秩r)进行小范围联合搜索。
    • 利用先验知识:不要从完全均匀的分布中采样。例如,学习率通常在对数空间(如1e-5到1e-3)搜索效果更好;LoRA的秩r通常从[8, 16, 32, 64]这类离散值中选取。将这些先验知识编码到Optuna的suggest_categoricalsuggest_loguniform中。
    • 设置早期停止:在Optuna的每个试验(Trial)内部,也要实现训练过程的早期停止。如果某个超参组合在训练初期(如20%的epoch)验证损失就远差于历史最佳,应立即终止该试验,节省资源。

5.3 评估指标的“欺骗性”与过拟合

自动化评估依赖预设的指标,但模型很容易“学会”去优化这些指标,而不是真正理解领域。

  • 陷阱表现:在自动构建的测试集上,模型的Rouge分数很高,但让真实领域专家一看,发现回答虽然包含了关键词,但逻辑混乱,或者存在事实性捏造(幻觉)。
  • 应对策略
    • 构建“对抗性”测试集:不要只从训练数据分布中采样构建测试集。可以有意构造一些边缘案例、有歧义的问题、或者需要多步推理的问题加入测试集。自动化系统可以集成一个“难题生成”模块,例如,让GPT-4基于领域知识生成一些具有挑战性的问题。
    • 采用多维度评估:单一指标不可靠。必须组合多种指标:
      • 基于规则的指标:关键词命中率、语法错误检查。
      • 基于嵌入的指标:BERTScore、Sentence-BERT相似度。
      • 基于LLM的指标:使用GPT-4/Claude进行成对比较(Pairwise Comparison)或打分。虽然成本高,但可以作为最终验收的“金标准”,不必在每次迭代中都使用。
    • 保留人工评估回路:在关键节点(如最终模型上线前),必须引入人工评估。自动化系统可以生成一个评估界面,将模型输出和参考答案并排展示,让领域专家进行打分或评价。这个反馈可以反过来用于优化自动化评估模型。

5.4 模型“遗忘”通用能力的隐形成本

领域适应是为了让模型在特定领域表现更好,但我们通常不希望它彻底忘记原有的通用知识和能力。

  • 陷阱表现:领域适配后的模型,在回答领域问题时很棒,但一旦问及通用常识或其它领域问题,表现比原模型还差,变得“偏科”严重。
  • 应对策略
    • 混合数据训练:在训练数据中混入一定比例(如5%-20%)的通用高质量语料(如C4The Pile的部分数据)。这能像一个正则化器,帮助模型保留通用能力。自动化系统需要提供一个选项,让用户选择是否加入以及加入多少通用数据。
    • 使用更参数高效的微调方法:像LoRA这类方法,由于只更新少量参数,对模型原有知识的破坏相对较小,天生具有缓解遗忘的优势。在全量微调时,则需要格外注意。
    • 评估通用能力:在自动化评估模块中,必须加入一小部分通用基准测试(如MMLU中的STEM或人文子集)。在最终报告中,同时呈现领域指标和通用指标的对比,让用户明确知晓适配带来的“trade-off”。

自动化领域适应是一个极具前景的方向,它能将大模型的应用门槛从算法专家降低到领域专家。然而,真正的“自动化”并非一劳永逸,而是将人的经验和判断,转化为可配置、可迭代的系统规则。当前阶段,一个成功的AutoAdapt系统更像是一个“强力助手”,它负责执行重复、繁琐的试验和流程,而人类工程师则负责设定边界、审核关键结果、处理极端案例。在设计这类系统时,时刻牢记“以人为本的自动化”,在关键环节保留人的监督和干预入口,远比追求全无人介入的“黑盒”魔法更为可靠和实用。从我们上面设计的MVP原型出发,逐步强化每个模块的智能和鲁棒性,同时建立严谨的评估与监控体系,是走向成熟AutoAdapt的务实路径。