通用Agent能处理各种开放任务,但在垂直领域里往往力不从心。医疗诊断需要理解医学术语和临床指南,法律咨询需要掌握法条和判例,金融分析需要熟悉财报结构和市场指标。这些专业知识不是简单加一段提示词就能获得的,需要系统性的领域建模和Skill设计。这篇文章讲清楚如何构建真正有用的领域特定Skill。
为什么通用Agent在垂直领域表现不佳
通用LLM在垂直领域的问题不是知识不够,而是知识太泛。它知道很多概念,但不清楚这些概念在特定领域里的精确含义、适用边界和相互关系。
以医疗领域为例。通用模型知道”高血压”是一种疾病,但它可能不清楚不同指南对高血压分级的细微差别,不知道某种降压药在特定并发症患者身上的禁忌,也无法准确理解检验报告中的各项指标含义和参考范围。这些细节对非专业人士是”过于专业”,对专业人士却是”基本常识”。
另一个问题是术语歧义。同一个词在不同领域有不同含义。“接口”在软件领域是API,在机械领域是连接件,在医学领域是皮肤创面。通用模型根据上下文能猜对大部分情况,但在专业场景中,猜错的代价很高。
还有业务规则的复杂性。垂直领域的操作往往不是”知道知识”就够的,还需要遵循特定的流程和规范。比如药物处方要遵循”诊断 -> 评估禁忌 -> 选择药物 -> 确定剂量 -> 监测指标”的流程,跳过任何一步都可能导致严重后果。这些规则是结构化的、强制性的,不能靠模型的”常识”来推断。
所以领域特定Skill的核心任务,就是把领域知识、术语体系和业务规则编码成Agent可以稳定执行的结构。
领域建模:从知识到结构
领域建模是构建专业Skill的第一步。目标是把领域专家头脑中的隐性知识,变成显性的、可计算的结构。
领域建模通常从概念模型开始。识别领域中的核心实体、属性和关系。以法律领域为例,核心实体包括案件、法条、当事人、法院、律师等。关系包括”案件适用法条""当事人委托律师""法院判决案件”等。
# 法律领域概念模型示例
domain: legal
entities:
Case:
attributes:
- caseNumber: string
- caseType: enum [civil, criminal, administrative]
- filingDate: date
- status: enum [filed, hearing, pending, closed]
Statute:
attributes:
- code: string
- article: string
- text: string
- effectiveDate: date
- category: string
Party:
attributes:
- name: string
- role: enum [plaintiff, defendant, third_party]
- entityType: enum [individual, corporate]
relations:
- name: applies_to
from: Statute
to: Case
attributes:
- relevanceScore: float
- interpretation: string
- name: involved_in
from: Party
to: Case
attributes:
- role: string
- claims: string[]
概念模型之后是流程模型。识别领域中的典型工作流程,把每个流程拆成步骤、决策点和分支条件。流程模型比概念模型更动态,它描述的是”什么时候做什么”。
# 法律案件分析流程
process: case-analysis
steps:
- id: extract-facts
name: 提取案件事实
input: [caseDescription, evidenceList]
output: [factTimeline, disputedFacts]
- id: identify-issues
name: 识别争议焦点
input: [factTimeline, disputedFacts]
output: [legalIssues, factualIssues]
- id: search-statutes
name: 检索适用法条
input: [legalIssues]
output: [applicableStatutes, relevantPrecedents]
- id: analyze-arguments
name: 分析双方论点
input: [factualIssues, applicableStatutes]
output: [plaintiffArguments, defendantArguments]
- id: evaluate-strength
name: 评估胜诉概率
input: [plaintiffArguments, defendantArguments, relevantPrecedents]
output: [strengthAssessment, riskFactors]
- id: generate-recommendation
name: 生成策略建议
input: [strengthAssessment, riskFactors]
output: [recommendedStrategy, alternativeOptions]
最后是规则模型。把领域中的约束、计算逻辑和判断标准编码成规则。规则模型通常是声明式的,便于维护和验证。
// 医疗领域规则示例
interface MedicalRule {
id: string;
condition: (patient: PatientData, context: ClinicalContext) => boolean;
action: (patient: PatientData) => Recommendation[];
priority: number;
source: string; // 规则来源,如临床指南
}
const hypertensionRules: MedicalRule[] = [
{
id: 'htn-001',
condition: (p, ctx) =>
p.systolicBP >= 140 || p.diastolicBP >= 90,
action: (p) => [{
type: 'lifestyle',
details: '建议低盐饮食、规律运动、控制体重'
}],
priority: 1,
source: '2023中国高血压防治指南'
},
{
id: 'htn-002',
condition: (p, ctx) =>
(p.systolicBP >= 160 || p.diastolicBP >= 100) &&
!p.hasContraindication('ACEI'),
action: (p) => [{
type: 'medication',
drug: 'ACEI',
details: '首选ACEI类降压药'
}],
priority: 2,
source: '2023中国高血压防治指南'
}
];
知识图谱:连接离散的知识
概念模型、流程模型和规则模型解决了”有什么”的问题,但知识之间的关联还需要知识图谱来承载。
知识图谱用图结构表示实体和关系,适合表达复杂的领域关联。在医学领域,疾病、症状、药物、检查、科室之间构成了庞大的知识网络。当Agent遇到一个症状时,可以通过图谱推理可能的疾病,再进一步查询相关的检查项目和用药建议。
// 医学知识图谱示例(Cypher查询语言)
// 创建实体
CREATE (d:Disease {name: '2型糖尿病', code: 'E11'})
CREATE (s:Symptom {name: '多饮', type: 'classic'})
CREATE (s2:Symptom {name: '多尿', type: 'classic'})
CREATE (drug:Drug {name: '二甲双胍', category: '口服降糖药'})
CREATE (check:Examination {name: '空腹血糖', unit: 'mmol/L'})
// 创建关系
CREATE (d)-[:HAS_SYMPTOM {frequency: 'common'}]->(s)
CREATE (d)-[:HAS_SYMPTOM {frequency: 'common'}]->(s2)
CREATE (d)-[:FIRST_LINE_TREATMENT]->(drug)
CREATE (d)-[:DIAGNOSTIC_CRITERIA {threshold: '>=7.0'}]->(check)
CREATE (drug)-[:CONTRAINDICATED {condition: '严重肾功能不全'}]->(d)
知识图谱的查询和推理是Agent调用专业知识的入口。当用户描述症状时,Agent先在图谱中匹配相关实体,然后通过关系遍历找到关联的诊断、治疗和检查建议。
# 基于知识图谱的推理
class MedicalReasoner:
def __init__(self, graph):
self.graph = graph
async def differential_diagnosis(self, symptoms: list[str]) -> list[Diagnosis]:
# 根据症状查找可能的疾病
query = """
MATCH (d:Disease)-[r:HAS_SYMPTOM]->(s:Symptom)
WHERE s.name IN $symptoms
RETURN d.name as disease,
count(r) as matching_symptoms,
collect(r.frequency) as frequencies
ORDER BY matching_symptoms DESC
"""
results = await self.graph.run(query, symptoms=symptoms)
diagnoses = []
for record in results:
disease = record['disease']
# 查询该疾病的其他症状用于鉴别
other_symptoms = await self.get_other_symptoms(disease, symptoms)
diagnoses.append(Diagnosis(
disease=disease,
confidence=self.calculate_confidence(record),
matchingSymptoms=record['matching_symptoms'],
missingSymptoms=other_symptoms,
suggestedExams=await self.get_diagnostic_exams(disease)
))
return diagnoses
知识图谱的构建不是一次性的。初始可以用公开的知识库如UMLS、Wikidata医学子集,但垂直领域的很多知识是业务特有的,需要持续从实际案例中提取和补充。建议建立知识更新机制,定期把Agent处理过的新案例中的知识提取出来,经过人工审核后加入图谱。
专业术语处理:消除歧义
术语是专业领域的基础。通用模型对术语的理解往往是”知道大概意思”,而不是”知道精确含义和上下文限制”。
术语词典是最基础的组件。收集领域内的专业术语,给出标准定义、同义词、反义词、相关概念和使用场景。
# 金融术语词典示例
terms:
- term: "市盈率"
abbreviation: "P/E"
definition: "股票价格与每股收益的比率,衡量股票估值水平"
synonyms: ["PE ratio", "price-earnings ratio"]
formula: "P/E = 股价 / 每股收益"
context: "估值分析"
interpretation:
high: "可能高估,或预期高增长"
low: "可能低估,或增长前景不佳"
compare: "同行业对比更有意义"
- term: "净资产收益率"
abbreviation: "ROE"
definition: "净利润与股东权益的比率,衡量股东投资回报"
formula: "ROE = 净利润 / 平均股东权益"
context: "盈利能力分析"
related: ["ROA", "杜邦分析"]
术语消歧在Agent处理用户输入时很重要。同一个词在不同语境下含义不同,Agent需要能根据上下文选择正确的释义。
# 术语消歧示例
class TermDisambiguator:
def __init__(self, term_dict):
self.terms = term_dict
def disambiguate(self, term: str, context: str) -> TermDefinition:
candidates = self.terms.get(term, [])
if len(candidates) <= 1:
return candidates[0] if candidates else None
# 用上下文计算每个候选的相关度
scores = []
for candidate in candidates:
score = self.context_similarity(context, candidate)
scores.append((candidate, score))
# 返回最相关的释义
scores.sort(key=lambda x: x[1], reverse=True)
return scores[0][0]
def context_similarity(self, context: str, candidate: TermDefinition) -> float:
# 基于领域上下文、相关术语和使用场景计算相似度
similarity = 0
# 上下文包含候选的领域标签
if candidate.domain in context:
similarity += 0.4
# 上下文包含相关术语
for related in candidate.related_terms:
if related in context:
similarity += 0.2
# 使用语义相似度模型
similarity += self.semantic_similarity(context, candidate.definition)
return similarity
术语标准化也很重要。用户在输入时可能使用口语化表达、缩写或错别字,Agent需要能映射到标准术语。比如用户说”血压高”应该映射到”高血压”,说”血糖有点高”应该映射到”高血糖”或进一步确认是空腹血糖还是餐后血糖。
业务规则引擎:把规范变成可执行逻辑
垂直领域的很多操作受制于规范、标准和法规。这些规则不能靠模型的”理解”来执行,需要显式的规则引擎。
规则引擎的核心是把业务规则从代码中分离出来,用声明式的方式定义,由引擎解释执行。这样规则可以独立维护和更新,不需要改代码。
// 规则引擎核心
interface RuleEngine {
evaluate(facts: FactBag): RuleResult[];
}
class DroolsLikeEngine implements RuleEngine {
private rules: Rule[] = [];
addRule(rule: Rule) {
this.rules.push(rule);
this.rules.sort((a, b) => b.priority - a.priority);
}
evaluate(facts: FactBag): RuleResult[] {
const results: RuleResult[] = [];
const workingMemory = new WorkingMemory(facts);
for (const rule of this.rules) {
if (rule.when(workingMemory)) {
const result = rule.then(workingMemory);
results.push(result);
// 如果规则标记为独占,停止后续规则
if (rule.salience === 'exclusive') break;
}
}
return results;
}
}
// 金融合规规则示例
const amlRules: Rule[] = [
{
name: '大额交易报告',
priority: 100,
when: (wm) => {
const tx = wm.get('transaction');
return tx.amount > 50000 && tx.type === 'cash';
},
then: (wm) => ({
action: 'report',
target: 'regulatory_authority',
deadline: '24h'
})
},
{
name: '可疑交易监控',
priority: 90,
when: (wm) => {
const tx = wm.get('transaction');
const history = wm.get('transaction_history');
return tx.amount > history.dailyAverage * 10;
},
then: (wm) => ({
action: 'flag',
reason: 'unusual_amount',
requiresReview: true
})
}
];
规则的可解释性在垂直领域很重要。当Agent做出一个决策时,用户需要知道是基于什么规则。规则引擎应该能输出触发的规则列表和匹配的事实,形成完整的推理链。
# 规则执行的可解释性
class ExplainableRuleEngine:
def evaluate_with_explanation(self, facts):
trace = ExecutionTrace()
for rule in self.rules:
match_result = rule.evaluate(facts)
trace.add_step(
rule_name=rule.name,
condition=rule.condition_text,
matched=match_result.matched,
bindings=match_result.bindings,
action=match_result.action if match_result.matched else None
)
if match_result.matched:
facts = self.apply_action(facts, match_result.action)
return {
'result': facts,
'trace': trace,
'explanation': self.generate_explanation(trace)
}
def generate_explanation(self, trace):
triggered = [s for s in trace.steps if s.matched]
explanation = f"决策基于 {len(triggered)} 条规则:\n"
for step in triggered:
explanation += f"- {step.rule_name}:{step.condition}\n"
explanation += f" 匹配事实:{step.bindings}\n"
explanation += f" 执行动作:{step.action}\n"
return explanation
场景适配:不同情境下的差异化处理
同一个领域,不同场景下的处理逻辑可能截然不同。以医疗领域为例,急诊和门诊的诊疗流程、优先级判断和风险容忍度都不一样。
场景适配需要在Skill层面做差异化设计。可以定义场景模板,每个模板包含特定的规则集、知识库子集、处理流程和输出格式。
# 医疗场景模板
scenarios:
emergency:
name: 急诊
priority: critical
rules: [triage-rules, emergency-protocols]
knowledge_base: emergency_medicine
workflow: rapid_assessment
time_constraints:
initial_assessment: "5min"
treatment_decision: "15min"
outpatient:
name: 门诊
priority: normal
rules: [standard-diagnosis-rules, prescription-guidelines]
knowledge_base: general_medicine
workflow: standard_consultation
time_constraints:
consultation: "30min"
follow_up:
name: 复诊
priority: normal
rules: [follow-up-rules, medication-adjustment]
knowledge_base: patient_history
workflow: follow_up_visit
requires_context: [previous_visit, current_meds, lab_results]
场景识别是适配的第一步。Agent需要根据用户输入的上下文判断当前处于什么场景。可以用分类模型,也可以基于规则的关键词匹配和上下文推断。
# 场景识别
class ScenarioDetector:
def __init__(self):
self.scenarios = {
'emergency': EmergencyScenario(),
'outpatient': OutpatientScenario(),
'follow_up': FollowUpScenario()
}
def detect(self, user_input: str, context: dict) -> Scenario:
# 基于关键词的初步判断
emergency_keywords = ['急诊', '急救', '突然', '剧痛', '昏迷', '出血']
if any(kw in user_input for kw in emergency_keywords):
return self.scenarios['emergency']
# 基于上下文的推断
if context.get('visit_type') == 'follow_up':
return self.scenarios['follow_up']
# 默认场景
return self.scenarios['outpatient']
案例分析:金融报告分析Skill
我们为一个投资机构构建了一个财报分析Skill,用于自动分析上市公司的季度和年度财报。
这个Skill的核心挑战在于财报数据的结构复杂性和分析逻辑的专业性。一份年报可能包含数百页内容,涉及资产负债表、利润表、现金流量表、附注和管理层讨论等多个部分。分析时需要跨表勾稽、同比环比、行业对比和异常检测。
领域建模阶段,我们定义了财报的核心实体:Report(报告)、FinancialStatement(报表)、AccountItem(科目)、Indicator(指标)。关系包括”报告包含报表""报表由科目组成""指标基于科目计算”。
// 财报数据结构
interface FinancialReport {
company: Company;
period: ReportingPeriod;
statements: FinancialStatement[];
}
interface FinancialStatement {
type: 'balance_sheet' | 'income_statement' | 'cash_flow';
items: AccountItem[];
}
interface AccountItem {
code: string;
name: string;
amount: number;
parentCode?: string;
notes?: string;
}
// 指标计算规则
interface IndicatorRule {
name: string;
formula: (items: AccountItem[]) => number;
unit: string;
interpretation: IndicatorInterpretation;
}
const indicators: IndicatorRule[] = [
{
name: '流动比率',
formula: (items) => {
const currentAssets = sumByCode(items, '1xxx'); // 流动资产
const currentLiabilities = sumByCode(items, '2xxx'); // 流动负债
return currentAssets / currentLiabilities;
},
unit: '倍',
interpretation: {
normal: { min: 1.5, max: 2.5 },
tooHigh: '资金利用效率可能偏低',
tooLow: '短期偿债能力可能不足'
}
}
];
知识图谱用于存储行业基准和历史数据。当分析一家公司的毛利率时,Skill会查询图谱中同行业其他公司的毛利率分布,判断这家公司的水平是偏高、正常还是偏低。
业务规则引擎处理异常检测。比如”应收账款增长率超过收入增长率50%""存货周转天数同比恶化超过30%""经营现金流连续两个季度为负”等规则,触发后Skill会在分析报告中标注风险点。
# 财报异常检测规则
class FinancialAnomalyDetector:
def __init__(self, rules, historical_data):
self.rules = rules
self.history = historical_data
def detect(self, report: FinancialReport) -> list[Anomaly]:
anomalies = []
for rule in self.rules:
if rule.check(report, self.history):
anomalies.append(Anomaly(
rule=rule.name,
severity=rule.severity,
description=rule.describe(report),
related_items=rule.get_related_items(report)
))
return anomalies
# 具体规则实现
anomaly_rules = [
RevenueReceivableMismatchRule(),
InventoryTurnoverDeteriorationRule(),
CashFlowWarningRule(),
RelatedPartyTransactionRule()
]
场景适配方面,这个Skill支持三种分析模式:快速概览(5分钟生成核心指标和风险提示)、标准分析(30分钟生成完整报告)、深度研究(2小时生成包含行业对比和估值分析的详细报告)。用户根据时间需求选择模式,Skill自动调整分析的粒度和范围。
上线后,这个Skill把分析师处理单份财报的时间从4小时降到了45分钟(标准模式),而且覆盖了更多人工容易遗漏的勾稽关系和异常指标。
最佳实践:构建可靠的领域Skill
构建领域特定Skill是一个系统工程,以下是一些经过验证的实践建议。
在领域建模上,不要试图一次性建完美模型。先覆盖核心场景,再逐步扩展。和领域专家紧密合作,用他们熟悉的语言和概念,而不是强行套用技术术语。
在知识管理上,区分稳定知识和动态知识。会计准则、医学指南这类稳定知识可以硬编码在规则里,市场价格、最新判例这类动态知识需要通过外部接口实时获取。
在术语处理上,建立双向映射。不仅要把用户输入映射到标准术语,也要在输出时把标准术语解释给用户。避免”只说行话”,也避免”过度简化”。
在规则设计上,优先用声明式规则而非过程式代码。规则更容易被领域专家理解和审核,也更容易维护和更新。但要确保规则引擎的性能,规则数量大时可能需要索引和预编译。
在场景适配上,明确定义场景的触发条件和边界。场景之间不应该有重叠的灰色地带,否则Agent会在多个场景间摇摆。每个场景的处理流程要完整,不能假设其他场景已经做了某些处理。
在质量保障上,建立领域特定的评估标准。通用评估指标如BLEU、ROUGE在垂直领域往往不够,需要设计任务特定的评估方法。比如医疗Skill要评估诊断准确率,法律Skill要评估法条引用正确率,金融Skill要评估计算准确性。
最后,领域Skill需要持续迭代。领域知识在更新,业务规则在变化,用户需求在演进。建立反馈闭环,收集实际使用中的错误案例和改进建议,定期更新模型和规则。一个停滞不前的领域Skill,很快就会变得不可靠。