跳到正文

05 / 05 · 2025.10 — 至今

◯◯株式会社(SES)

在日本以 SES 形式参与遗留系统现代化相关开发:用 ANTLR4 + RAG + MCP 自动生成 COBOL 功能说明书,为某大型电机厂商的部门系统开发人员与组织同步工具,并作为担当者设计 CMD → C# 的“规则 + 生成式 AI”自动转换系统。

职位
开发工程师(Python)
行业
受托开发 · 遗留系统现代化(SES)
地点
日本
在职
1 年 1 个月

关键成果

  • 1,084 条

    CMD → C# 转换所用的外部命令映射表(另有 33 个内建命令、27 种 AST 节点)

  • 约 30 个课

    人员组织自动同步工具覆盖的组织规模(4 个部)

  • 4 个

    经 MCP 提供给模型的检索工具,用来按需查询 COBOL 变量的业务含义

在这里做的项目

PROJECTS · 3

2026.04 – 至今 · 担当者(架构设计・核心开发・评审)

遗留批处理(CMD/JCL)→ C# 自动转换系统

将长期运行的 Windows 批处理脚本(CMD,Shift-JIS 编码)迁移为运行在自研批处理框架上的 C# 程序。人工逐本改写工时高、业务逻辑等价性难以保证,因此构建“规则转换 + 生成式 AI 补全”的两阶段自动转换系统,并以“宁可留 TODO,也不静默改变业务逻辑”为设计原则。

  • 两阶段架构设计:阶段一用确定性规则完成大部分转换(预处理 → Lark 语法解析 → AST → 规则引擎 → C# 生成);阶段二仅对规则无法覆盖的 CALL :标签 子程序调用 LLM 生成 C# 方法,把 AI 的使用范围和风险压到最小
  • CMD 语法建模:编写并持续扩展约 490 行 Lark(LALR)文法,处理重定向符可出现在任意位置、< > & | 的二义性、%VAR:old=new% 置换、IF/ELSE 的多种括号写法、含日文的标签名等 cmd.exe 的怪癖
  • 输入归一化层(8 类预处理):在不改变语义的前提下统一混杂换行、行尾粘连括号、多行 ELSE、ECHO 元字符、全角空格等“脏数据”,让文法保持简洁
  • AST 与规则引擎:27 种自定义 AST 节点;33 个内建命令 + 1,084 条外部命令映射表(区分“作业进程”与“作业流”两种调用模式);变量展开区分字符串、参数行、整数表达式三种上下文
  • LLM 子程序转换与“语义保留”校验:LabelMapper 将 .cs 的 TODO、.cs.ast 的调用节点、.cmd 原文三方对齐;结构 + 业务语义两层校验(ERRORLEVEL、取消分支、错误跳转、状态标志必须保留);失败时带原因反馈重试最多 7 次,仍失败则保留 TODO 交人工
  • 成本与稳定性:以标签块归一化内容的 SHA256 为键做 JSON 缓存;429 / 5xx 指数退避;Chat Completions 不可用时自动降级到 Responses API;temperature=0 保证可复现
  • 质量闭环:约 465 个测试用例覆盖文法层与转译层;批量运行产出 .cs.ERR,按“CMD 原文问题 / 文法缺口 / 代码缺陷 / 环境”四类分类,并整理常见错误清单供团队复用
  • Python
  • Lark (LALR)
  • regex
  • Azure OpenAI
  • C# / .NET
  • pytest
  • Git

系统架构

两阶段转换架构
遗留 CMD 脚本Shift-JIS 批处理 阶段一 · 确定性转译流水线 预处理8 类归一化 LALR 解析Lark 490 行文法 AST 变换27 种节点 C# 生成类 / Main / using 规则引擎 + 变量展开33 内建命令 + 1,084 条映射 一次产物.cs (含 TODO) · .cs.ast · .utf8.cmd 阶段二 · AI 补全 CALL :LABEL 三方对齐TODO·AST·CMD 缓存查询SHA256 哈希 Azure OpenAItemperature 0 两层校验结构 + 业务语义 反馈式重试最多 7 次,仍失败留 TODO 最终产物.label.ai.cs(不覆盖原 .cs)

2026.01 – 2026.03(3 个月) · Python 同步工具的开发、测试、上线与运维交接(派遣)

部门项目管理系统 · 人员组织自动同步工具

某大型电机厂商的软件技术部门以开源 Redmine 为底座,自建项目管理与状况报告平台(Angular + Go + Redmine)。人员与组织数据来自社内人员目录,而该目录没有可用的对外接口,因此我负责开发同步工具:用 Selenium 爬取成员与组织架构,自动同步为 Redmine 的账号、部 / 课组织与权限组,覆盖 4 个部、约 30 个课。

  • 数据源迁移:原人员目录停用后,将爬虫迁移到新站点,适配新页面结构与微软 SSO 登录,并兼容旧的职务标识,下游同步逻辑无需修改
  • 用 Selenium(Edge Headless)自动登录并遍历组织树,逐人检索所属与职务;通过 paramiko SFTP 将结果从内网 PC 单向推送到 Azure 服务器
  • 同步批处理:新旧数据差分,自动生成并执行 SQL,完成账号开通、停用、再入职解锁及部 / 课 / 职务同步;经 Redmine REST API 同步状况报告权限组,白名单成员不受影响
  • 用 SendGrid 实现 3 类异常告警;检测到意外的组织变更时自动中止,SQL 由担当者确认后再执行(两阶段),避免错误数据直接写入本番
  • 将分散在代码里的部门映射集中到数据库配置表;按客户方针对应 4 月组织变更,设计并执行覆盖页面、申请流程和权限组的测试用例
  • 定位并修复本番问题:重复人员导致的锁定误判、再入职账号缺失、网络波动导致的页面超时、Edge 驱动版本不匹配
  • 负责两套本番环境(内网运用 PC + Azure VM)上线:备份、部署、关闭写库试运行核对 SQL,再正式运行;编写运维手顺书(部署、告警说明、排错、组织变更 SOP)并完成交接
  • 用 Fortify / FOSSology 对全项目做安全与许可证扫描,修复 JSON 注入、SQL 注入等高危指摘,整理 OSS 许可证清单
  • Python
  • Selenium
  • paramiko
  • MySQL / MariaDB
  • Redmine REST API
  • SendGrid
  • Bash
  • PowerShell
  • Azure VM

系统架构

① 客户内网 · WINDOWS 运用 PC ② AZURE VM · 本番服务器 任务计划程序 → executor.ps1 先运行 Excel 宏导出正式员工白名单 find_users_emails_and_departments 自动完成微软 SSO 登录 展开组织树,逐个部 / 课抓取邮箱 → new_users / new_organization.csv generate_all_users_data 按邮箱逐人检索:所属、职务、姓名 → all_users_data.csv transport_csv paramiko 按时间戳目录 SFTP 上传 remove_old_dir 清理过期 CSV 和日志 每步独立子进程,失败即中止后续步骤 社内人员目录 社内人员目录 (旧目录系统 已停用) 组织树 员工检索 SFTP cron → executor.sh 找到当天最新的数据目录 SFTP 接收目录 专用账号 · batchgroup 权限 manage_user_batch(11 个步骤) 1 csv_validator:表头、邮箱格式、危险字符 2 组织差分 → update_organization.sql 组织意外变更 → 退出码 2 → 中止并告警 3 人员差分 → update_users.sql 新成员开通 · 离开者停用 · 再入职解锁 4 权限组差分 → curl 脚本 状况报告组 · 部门内负责人组 · 白名单组保留 5 执行 SQL / 脚本 → 清理旧目录 两阶段执行 EXEC_UPDATE_USER_SQL_FLAG 控制是否直接写库 组织变更时先生成 SQL,担当者确认后 执行 executor_after_confirmed.sh MySQL(Redmine 库) users · email_addresses 部门 / 部 / 课 · 职务 · config Redmine REST API 组成员增删 SendGrid 3 类告警邮件 系统担当者 确认 SQL 后手动放行
客户社内网络 · WINDOWS PC AZURE VM · DOCKER COMPOSE 浏览器用户 部门成员 · 管理层 · 审批者 Apache(Bitnami)HTTPS 反向代理 /home /dashboard_* /project_mgmt → Angular /dashapi → Go API 其余 → Redmine Angular 18 SPA nginx 容器 · 13 个页面 Dashboard / 报告 / 统计图 项目申请 · 审批 · 权限守卫 Go API(Gin) 40+ REST 接口 · OpenAPI Worker Pool 并发拉取 Issue 事务 + 行锁 · 审批流 Redmine Issue / Tracker / 自定义字段 项目 · 成员 · 组 · 权限 注入自定义 JS / CSS REST API API Key SendGrid 外部邮件 API 审批通知 扩展表读写 MySQL(与 Redmine 共库) Redmine 原生表:users · email_addresses · groups_users · issues … 扩展表:departments · sections · divisions · user_*(部门/部/课 × 职务) application_requests · application_operation_logs · config user_queries(保存检索条件)· lock_table(并发控制) 异常告警邮件 执行生成的 SQL manage_user_batch(Python · cron)★ 我负责 ① CSV 校验 → ② 组织架构差分 → ③ 生成用户新增 / 停用 SQL ④ 同步部/课组织与职务 → ⑤ 同步状况报告权限组成员 组织结构意外变更 → 退出码 2 中止 + 邮件告警 人工确认后执行第二阶段(executor_after_confirmed) SFTP 接收目录 专用 sftpuser · batchgroup cron 按日期找最新文件夹 社内人员目录 Microsoft SSO 登录 · 组织树 模拟登录 + 遍历 cross_page_batch ★ 我负责 Selenium + Edge Headless 自动完成 MS 账号登录 逐层展开部 / 课节点抓取邮箱 按邮件列表白名单过滤 重试 · 显式等待 · 日志 白名单来自 Excel 宏工具 CSV 产物 new_users.csv new_organization.csv transport_csv paramiko SFTP 上传 按时间戳建远端目录 SFTP

2025.10 – 2025.12(3 个月) · 方案设计、实现、验证(个人主导)

基于 ANTLR4 + RAG + MCP 的 COBOL 功能说明书自动生成

客户的核心批处理仍运行在几十年前编写的 COBOL 程序上:没有可用的设计文档,TR1-HINSHU 这类缩写变量的业务含义散落在数据库设计手册与术语表中,熟悉 COBOL 的人员也越来越少。目标是输入 COBOL 源码,自动输出业务人员也能读懂的日文功能说明书(Markdown)。设计原则:确定性的事情交给程序(语法、布局、调用关系),模型只负责“赋予含义并写成文字”。

  • 模型能力验证与方向调整:对 Gemma-3 4B 做 COBOL 理解基准测试;在 Colab 上尝试 LoRA 微调但受显存所限无法完成。因业务词典随客户变化,转向无需重新训练的 RAG 方案
  • 知识库构建:把数据库设计手册、术语表、表 / 文件 / 作业流定义统一为 {key, value},按“文件 → 记录 → 字段 → 组字段”的层级做语义切分;仅对 key 向量化(multilingual-e5-small)存入 ChromaDB,并在检索前去除 OCCURS 下标、建立别名与层级路径
  • COBOL 解析:基于 Cobol85.g4 生成 Python 的 Lexer / Parser / Visitor;预处理 Shift_JIS → UTF-8、去除行号、处理 $SET 等方言指令;把解析树转成面向 LLM 的精简 AST;变量提取器支持 REDEFINES / OCCURS / COMP / 88 级
  • 调用层级分析:由 PERFORM 构建调用图,过滤 RTN / EXT 配对中只起出口作用的 EXT 段落,用拓扑排序确定自底向上的分析顺序
  • MCP 集成:用 FastMCP 把向量检索封装成 lookup_field / lookup_record / batch_lookup_fields / get_subroutine_summary 四个工具,模型只检索当前用到的变量,避免把几百个变量定义全部塞进上下文
  • 生成与提示词调优:逐个子程序抽取输入 / 输出 / 工作变量与被调用子程序,经 MCP 检索定义并带入下层摘要,由 Gemma-3 生成 Markdown;通过约束提示词去掉空项,并要求用业务语言描述而非直译 MOVE 语句
  • Python
  • ANTLR4
  • ChromaDB
  • SentenceTransformers
  • MCP (FastMCP)
  • Gemma-3 4B
  • Hugging Face Transformers
  • Google Colab
  • WSL

系统架构

知识库 + MCP + 说明书生成流水线
① 离线 · 知识库构建(一次性) 资料 数据库设计手册 · 术语表 表 / 文件 / 作业流定义 语义切分 文件 → 记录 → 字段 → 组 统一为 {key, value} 只对 key(字段 ID)向量化 向量化 multilingual-e5-small 日 / 中 / 英检索 ChromaDB 别名:去除 OCCURS 下标 保留层级路径 MCP 服务器(FastMCP) lookup_field · lookup_record batch_lookup_fields · get_subroutine_summary 向量检索封装成工具 ② 在线 · 说明书生成(每个程序一次) COBOL 源码 Unisys 方言 预处理 Shift_JIS → UTF-8 去行号 · 方言指令 ANTLR4 解析 Cobol85.g4 → AST 调用图 + 拓扑排序 PERFORM · 过滤 EXT 段 自底向上 Gemma-3 4B 逐子程序生成 功能说明书 .md(日文) 按需检索变量定义 确定性的事交给程序(语法、布局、调用关系),模型只负责“赋予含义并写成文字”

系统数据流

抽象示意 · 不含内部细节
  1. 遗留 CMD 脚本

    Shift-JIS · 自治体系统

  2. 归一化 + Lark 解析

    8 类预处理 · 约 490 行文法

    ▲ 我负责的部分

  3. 规则引擎

    33 内建 + 1,084 外部映射

    ▲ 我负责的部分

  4. C# 代码生成

    .cs · 未覆盖处留 TODO

  5. LLM 补全 + 两层校验

    CALL :标签 · 最多 7 次重试

    ▲ 我负责的部分

  6. 产物

    .label.ai.cs · 失败保留 TODO

在这里学到了什么

为了能长期在日本工作,我 2024 年 7 月来日,先在日语学校学习日语并取得 N2,2025 年 11 月退学后以 SES 形式进入日本的开发现场。

三个案件都围绕“让遗留系统更容易被理解和迁移”:COBOL 项目让我体会到 RAG 的质量取决于切分粒度和检索 key 的设计;人员同步工具里,在内网隔离、没有接口的条件下,靠单向推送、两阶段执行和告警来保护本番数据;CMD → C# 转换则确立了一个原则——确定性的事情交给程序,生成式 AI 只负责规则写不动的最小单元,并且每个输出都要过校验,宁可留 TODO,也不静默改变业务逻辑。

TECH STACK

  • Python
  • Lark
  • ANTLR4
  • Azure OpenAI
  • MCP
  • ChromaDB
  • Selenium
  • C# / .NET
  • Redmine REST API
  • MySQL / MariaDB
  • Azure VM