Files
cobol-java-v3/docs/detailed-design/05-agents-llm.md
T

25 KiB
Raw Blame History

05 - LLM 代理模块详细设计

1. 模块概述

LLM 代理模块(agents/)是 COBOL 迁移验证平台 V3 的智能分析层,负责通过大语言模型(LLM)完成三项核心任务:

  1. COPYBOOK 解析Agent1):将 COBOL COPYBOOK 源码解析为结构化字段树(FieldTree
  2. 测试数据设计(Agent2):基于字段树生成边界测试用例(TestSuite
  3. 差异诊断Agent3):对 COBOL/Java 字段比对不一致项进行根因分析与建议

此外,模块还包含一个式样书驱动测试数据生成器DesignDataGenerator),通过解析日文详细设计书,结合 LLM 生成有业务意义的机能测试数据。

模块底层封装了统一的 LLMClient,提供缓存、重试、多模型兼容能力。

2. 文件清单

文件 职责 依赖
__init__.py 包入口,公开 API 导出 所有子模块
llm.py LLM API 客户端(缓存 + 重试) httpx
agent1_parser.py COPYBOOK → FieldTree 解析代理 llm.py, data.field_tree
agent2_data.py FieldTree → TestSuite 测试数据设计代理 llm.py, data.field_tree, data.test_case
agent3_diagnostic.py FieldResult → 诊断建议文本代理 llm.py, data.diff_result
design_data.py 式样书驱动测试数据生成器 llm.py, design_data_input_parser
design_data_input_parser.py 式样书 .md 解析器 标准库 re, dataclasses

3. Agent 架构模型(感知-规划-行动-记忆)

本节描述 LLM 代理模块的核心架构模型,采用经典的感知-规划-行动-记忆Perception-Planning-Action-Memory)循环。

3.1 架构图

┌─────────────────────────────────────────────────────────────────────────────┐
│                        Agent 架构模型 (感知-规划-行动-记忆)                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                         感知层 (Perception)                           │  │
│  │                                                                      │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │  │
│  │  │ COBOL源码   │  │ COPYBOOK    │  │ 设计书.md   │  │ 比对结果    │ │  │
│  │  │ 输入        │  │ 结构        │  │ 业务规则    │  │ 差异项      │ │  │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘ │  │
│  │         │                │                │                │         │  │
│  │         └────────────────┼────────────────┼────────────────┘         │  │
│  │                          ▼                                           │  │
│  │              ┌───────────────────────┐                               │  │
│  │              │ read.py / DesignData  │                               │  │
│  │              │ InputParser           │                               │  │
│  │              └───────────┬───────────┘                               │  │
│  └──────────────────────────┼───────────────────────────────────────────┘  │
│                             │                                               │
│                             ▼                                               │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                         规划层 (Planning)                             │  │
│  │                                                                      │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │  │
│  │  │ 字段树构建  │  │ 路径枚举    │  │ 约束生成    │  │ 测试策略    │ │  │
│  │  │ FieldTree   │  │ BranchTree  │  │ Constraints │  │ TestSuite   │ │  │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘ │  │
│  │         │                │                │                │         │  │
│  │         └────────────────┼────────────────┼────────────────┘         │  │
│  │                          ▼                                           │  │
│  │              ┌───────────────────────┐                               │  │
│  │              │ core.py / design.py   │                               │  │
│  │              │ enum_paths            │                               │  │
│  │              └───────────┬───────────┘                               │  │
│  └──────────────────────────┼───────────────────────────────────────────┘  │
│                             │                                               │
│                             ▼                                               │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                         行动层 (Action)                               │  │
│  │                                                                      │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │  │
│  │  │ LLM调用     │  │ 规则引擎    │  │ 数据生成    │  │ JSON输出    │ │  │
│  │  │ DeepSeek    │  │ Fallback    │  │ Records     │  │ output.py   │ │  │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘ │  │
│  │         │                │                │                │         │  │
│  │         └────────────────┼────────────────┼────────────────┘         │  │
│  │                          ▼                                           │  │
│  │              ┌───────────────────────┐                               │  │
│  │              │ agents/llm.py         │                               │  │
│  │              │ LLMClient.call()      │                               │  │
│  │              └───────────┬───────────┘                               │  │
│  └──────────────────────────┼───────────────────────────────────────────┘  │
│                             │                                               │
│                             ▼                                               │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                         记忆层 (Memory)                               │  │
│  │                                                                      │  │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │  │
│  │  │ pi_map      │  │ assignments │  │ 决策点缓存  │  │ LLM缓存     │ │  │
│  │  │ 字段映射    │  │ 赋值链      │  │ DecisionPts │  │ .cache/llm  │ │  │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘ │  │
│  │         │                │                │                │         │  │
│  │         └────────────────┼────────────────┼────────────────┘         │  │
│  │                          ▼                                           │  │
│  │              ┌───────────────────────┐                               │  │
│  │              │ models.py / config    │                               │  │
│  │              │ 共享数据模型          │                               │  │
│  │              └───────────────────────┘                               │  │
│  └──────────────────────────────────────────────────────────────────────┘  │
│                                                                             │
│  ┌──────────────────────────────────────────────────────────────────────┐  │
│  │                         循环反馈 (Feedback Loop)                      │  │
│  │                                                                      │  │
│  │  覆盖率分析 → 未覆盖分支 → 补充测试数据 → 重新执行 → 更新记忆        │  │
│  │  (coverage.py)  (DecisionPoints)  (design.py)  (runners/)  (pi_map) │  │
│  └──────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────┘

3.2 四层职责

层级 职责 核心组件 数据模型
感知层 解析输入,提取结构信息 read.py, DesignDataInputParser COBOL源码, FieldTree
规划层 构建分支树,枚举路径,生成约束 core.py, design.py, cond.py BranchTree, Constraints
行动层 执行LLM调用,生成测试数据 agents/llm.py, output.py TestSuite, JSON
记忆层 缓存中间结果,共享状态 models.py, config/ pi_map, assignments

3.3 循环反馈机制

Agent 架构采用闭环反馈设计:

  1. 感知 → 规划: 解析结果驱动分支树构建
  2. 规划 → 行动: 路径约束指导测试数据生成
  3. 行动 → 记忆: 生成结果更新缓存和状态
  4. 记忆 → 感知: 覆盖率分析触发新一轮感知

3.4 LLM 在架构中的位置

┌─────────────────────────────────────────────────┐
│                  Agent 架构                      │
├─────────────────────────────────────────────────┤
│                                                 │
│   规划层                行动层                   │
│   ┌─────────────┐      ┌─────────────┐         │
│   │ 路径枚举    │      │ LLM调用     │         │
│   │ (规则引擎)  │──────│ (DeepSeek)  │         │
│   └─────────────┘      └─────────────┘         │
│         │                      │                │
│         │    ┌─────────────┐   │                │
│         └────│ 记忆层      │───┘                │
│              │ (缓存+状态) │                    │
│              └─────────────┘                    │
└─────────────────────────────────────────────────┘

LLM 作为行动层的核心组件,负责:

  • Agent1: COPYBOOK → FieldTree 解析
  • Agent2: FieldTree → TestSuite 测试数据设计
  • Agent3: FieldResult → 诊断建议文本
  • DesignDataGenerator: 式样书 → 机能测试数据

当 LLM 调用失败时,系统自动降级到规则引擎(fallback),确保流水线不中断。

3.5 记忆层详解

记忆层是 Agent 架构的状态中心,存储:

记忆类型 说明 位置
短期记忆 单次执行的中间结果 pi_map, assignments
长期记忆 跨执行的缓存数据 .cache/llm/
共享记忆 模块间传递的数据 models.py

4. Agent1 解析代理(Agent1Parser

3.1 职责

将 COBOL COPYBOOK 源码文本发送给 LLM,由 LLM 输出结构化 JSON,再转换为 FieldTree 对象。这是整个流水线的第一步——只有正确解析字段结构,后续测试生成和比对才有基础。

3.2 数据流

COPYBOOK 源码文本
    ↓ (LLM call)
JSON: {"fields": [{name, level, pic, usage, offset, length, decimal, signed, occurs, redefines, conditions, children}]}
    ↓ (_load / _fields 递归)
FieldTree

3.3 核心类

class Agent1Parser:
    def __init__(self, llm: LLMClient)
    def parse(self, text: str) -> FieldTree
    def _load(self, d: dict) -> FieldTree
    def _fields(self, raw: list[dict], off: int) -> list[Field]

3.4 LLM 提示词

系统提示词(P1)要求 LLM 扮演 COBOL COPYBOOK 解析器角色,输出严格 JSON 格式,包含字段的名称、层级、PIC 子句、USAGE 类型、偏移量、长度、小数位、符号、OCCURS、REDEFINES、88-level 条件及子字段嵌套。

3.5 字段偏移量计算

_fields 方法递归遍历 JSON 字段列表,逐字段计算字节偏移量(cur += f.length),确保每个字段在记录中的物理位置准确。子字段通过递归调用 _fields 处理嵌套层级。

3.6 错误处理

  • LLM 返回非法 JSON 时,parse 捕获异常,返回一个 FieldTree(copybook_name="parse_error") 空树
  • 使用 bare except 捕获所有解析异常,保证流水线不中断

5. Agent2 数据生成代理(Agent2Data

4.1 职责

基于 FieldTree 结构,通过 LLM 生成边界测试用例集合(TestSuite)。每个测试用例指定字段值和覆盖目标决策点。

4.2 数据流

FieldTree
    ↓ (flatten → JSON)
{"fields": [{name, pic, usage, length, decimal, signed}]}
    ↓ (LLM call)
{"test_cases": [{id, fields: {FIELD: value}, coverage_targets: [DP-001]}]}
    ↓ (构造 TestCase)
TestSuite

4.3 核心类

class Agent2Data:
    def __init__(self, llm: LLMClient)
    def design(self, tree: FieldTree, target="boundary", spark_mode=False) -> TestSuite

4.4 LLM 提示词

系统提示词(P2)要求 LLM 扮演 COBOL 测试数据设计师角色,根据字段树生成边界测试用例,输出严格 JSON 格式。

4.5 Spark 模式

spark_mode=True 时,生成的 TestSuite 附带 SparkConfig(num_records=1000),用于大数据量测试场景。

4.6 错误处理

  • LLM 调用失败或返回非法 JSON 时,生成一条兜底用例 TestCase(id="TC-FALLBACK", fields={"BR-AMT": 0})
  • 使用 bare except 捕获反序列化异常

6. Agent3 诊断代理(Agent3Diagnostic

5.1 职责

对单个字段比对结果(FieldResult)进行根因分析,输出包含问题类型、置信度、原因和建议的 JSON 诊断文本。

5.2 数据流

FieldResult (field_name, cobol_value, java_value, status)
    ↓ (格式化 prompt)
LLM call
    ↓
JSON: {"issue_type": "...", "confidence": 0.5, "reason": "...", "suggestion": "..."}

5.3 核心类

class Agent3Diagnostic:
    def __init__(self, llm: LLMClient)
    def analyze(self, fr: FieldResult) -> str

5.4 LLM 提示词

系统提示词(P3)明确要求 LLM 不做 PASS/FAIL 判定,仅提供诊断分析。这是设计上的重要约束——Agent3 只是辅助分析工具,最终判定由比对引擎完成。

5.5 错误处理

  • 依赖 LLMClient.call() 的重试机制
  • 返回原始 LLM 响应字符串,调用方负责解析

7. 式样书驱动测试数据生成器(DesignDataGenerator

6.1 职责

从日文详细设计书(.md)中提取程序元信息(ProgramMeta),结合 COBOL 源码、COPYBOOK 结构和 DB 定义,通过 LLM 生成有业务意义的机能测试数据。

6.2 数据流

设计书 .md + COBOL 源码
    ↓ (DesignDataInputParser.parse)
ProgramMeta (program_id, pgm_pattern, files, keys, process_detail, ...)
    ↓ (加载规则 + 构建 prompt)
LLM call
    ↓
JSON: {"records": [{field_name: value}]}
    ↓ (_resolve_field_names 字段名映射)
list[dict]

6.3 核心类

class DesignDataGenerator:
    def __init__(self, llm_client: LLMClient, cpy_dirs: list, rules_dir: str = "rules")
    def generate(self, design_md_text, source_text, file_db_md_text=None,
                 db_md_text=None, replacing_rules=None, v3_field_names=None) -> list[dict]

6.4 式样书解析器(DesignDataInputParser

解析日文详细设计书 Markdown 文档,提取以下结构化信息:

数据类 内容
ProgramMeta 程序ID、程序名、系统名、PGM类型、PGM模式、功能概要
FileInfo 文件编号、文件/DB名、标识符、DD名、I/O类型、COPY群、记录格式、记录长度、媒体
KeyInfo 键文件名、排序条件、键条件
ModuleInfo 模块编号、功能、程序ID、COPY名
TableInfo 表名、DB ID、列定义、主键列

解析通过 Markdown 标题匹配(## 基本情報## 使用ファイル一覧 等)和表格解析实现,不依赖外部 Markdown 解析库。

6.5 输入类型自动判定

_determine_input_type 根据输入文件的媒体类型自动判定:

媒体类型 input_type
仅 PS(顺序文件) file
仅 DB(数据库) db
混合或无输入 mixed / file

6.6 字段名映射(_resolve_field_names

外部 Agent 生成的字段名可能与 V3 内部字段名不一致,映射规则:

  1. REPLACING 展开(A)R01
  2. 前缀连字符处理R01-EMP-IDR01EMP-ID
  3. 直接匹配:精确匹配 V3 字段名
  4. 去连字符匹配R01EMP-IDR01EMPID
  5. 去下划线匹配R01_EMP_IDR01EMPID
  6. 无法映射的字段丢弃

6.7 规则加载

_load_rulesrules/pgm_pattern/rules/special_feature/ 目录加载所有 .md 规则文件,作为 LLM 上下文的一部分。

6.8 记录去重(_dedup

支持按指定键字段去重,additional_records 优先保留。

8. LLM 接口封装(LLMClient

7.1 职责

封装 LLM API 调用,提供文件缓存、自动重试、多模型兼容能力。所有 Agent 通过此客户端与 LLM 交互。

7.2 核心类

class LLMClient:
    def __init__(self, model="gpt-4o-mini", timeout=15, cache_dir=".cache/llm")
    def call(self, messages: list[dict], retries=1) -> str
    def _key(self, msgs: list[dict]) -> str       # SHA256 哈希键
    def _get(self, k: str) -> str | None           # 缓存读取
    def _set(self, k: str, v: str) -> None         # 缓存写入

7.3 缓存机制

  • 键生成:对消息列表进行 JSON 序列化后取 SHA256 哈希
  • 存储:以 {hash}.json 文件存储在 .cache/llm/ 目录
  • 格式{"response": "..."}
  • 效果:相同输入直接返回缓存结果,避免重复调用 LLM

7.4 重试机制

  • 默认重试 1 次(共 2 次尝试)
  • 使用 httpx.post 发送 HTTP 请求
  • 重试时捕获所有异常,仅在最后一次失败时抛出

7.5 环境变量配置

环境变量 说明 默认值
LLM_API_KEY API 密钥 空字符串
OPENAI_API_KEY 备用 API 密钥 空字符串
LLM_API_BASE API 基础 URL https://api.openai.com/v1

7.6 API 调用格式

POST {base}/chat/completions
{
  "model": "{model}",
  "messages": [...]
}
Header: Authorization: Bearer {key}

响应解析路径:response["choices"][0]["message"]["content"]

9. 接口定义

8.1 模块公开 API

# agents/__init__.py
LLMClient              # LLM API 客户端(含缓存 + 重试)
Agent1Parser           # COPYBOOK → FieldTree
DesignDataGenerator    # 式样书 → 机能测试数据
Agent2Data             # FieldTree → TestSuite(测试数据设计)
Agent3Diagnostic       # FieldResult → 诊断建议文本

8.2 典型调用链

Agent1Parser.parse(copybook_text) → FieldTree
Agent2Data.design(field_tree) → TestSuite
DesignDataGenerator.generate(design_md, source_text) → list[dict]
Agent3Diagnostic.analyze(field_result) → str (JSON)

8.3 数据模型依赖

模型 定义位置 用途
FieldTree data.field_tree 字段树结构
Field data.field_tree 单个字段定义
TestCase data.test_case 单条测试用例
TestSuite data.test_case 测试用例集合
SparkConfig data.test_case Spark 生成配置
FieldResult data.diff_result 字段比对结果

10. 错误处理

9.1 错误策略

模块采用宽容降级策略:

异常场景 处理方式 影响
LLM 返回非法 JSON 返回空/兜底结果 流水线继续
LLM API 调用失败 重试后抛出异常 上层捕获
式样书解析失败 返回空列表 跳过数据生成
字段名映射失败 丢弃无法映射的字段 部分数据丢失
缓存文件损坏 跳过缓存,重新调用 无功能影响

9.2 日志策略

  • 使用 Python logging 模块
  • 关键步骤记录 INFO 级别日志(解析开始、LLM 响应、记录数)
  • 异常记录 WARNING 级别日志
  • 字段映射丢弃记录 DEBUG 级别日志

9.3 已知局限

  1. Agent1/Agent2/Agent3 的 bare except 可能掩盖非预期异常
  2. 缓存键基于消息内容哈希,模型变更不会自动失效旧缓存
  3. DesignDataGenerator 的 LLM prompt 包含截断(process_detail[:2000]),超长设计书可能丢失信息