
这阵子接了个挺让我头疼的活给 ABAP 开发组的几十个自定义类补文档。我一开始还以为就是套模板结果越补越觉得不对劲——大家写代码时根本没留 ABAPDoc功能逻辑全在脑子里补文档的效率和准确率都低得离谱。后来我干脆把 AI 接进了 SAP做了个 ZLLM 小工具让它在 SE80 这些标准入口里直接读懂源码、生成 ABAPDoc再把文档写回 SAP 的文档存储。今天就把这套思路和踩过的坑完整分享出来给同样被文档折磨的 ABAP 顾问和开发一个可直接复用的参考。这个方案解决的不只是“省时间”的问题。它真正改变的是 ABAP 开发日常里“文档永远最后补”这个习惯。传统的文档工作流是代码写完后单独抽时间补而 ZLLM 的思路是把文档生成嵌进开发行为本身开发者在 SE80 里打开一个类或者一个程序调起工具AI 基于源码自动生成结构化的 ABAPDoc 注释和标准对象说明再写回 SAP 对应的文档对象。整个过程不需要离开标准界面也不需要切到外部编辑器。如果你刚接触 AI 辅助开发这套方案能给你一个很直观的切入点原来 SAP 也能用上大模型而且是用在最不起眼但最耗精力的文档环节上。1. 先说说我为什么要在 ABAP 开发里折腾 ZLLM1.1 ABAP 项目的文档债真的不只是懒的问题在 ABAP 项目里干了十几年我见过太多“代码在手文档没有”的场面。每个人都知道 ABAPDoc 注释、函数模块说明、事务代码描述是硬规范但真到交付节点能补齐的人少之又少。原因不复杂ABAP 的对象体系太庞大了一个类可能带十几个方法一个函数组里几十个函数模块要给每个对象写清楚“干什么用、参数怎么传、异常在什么情况下触发”纯手工工作量非常大而且特别容易写成了“流水账”。更麻烦的是文档缺乏即时性。很多开发者在编码时头脑里有完整的上下文等过了两周再回头看代码思路已经断了一半补出来的文档往往跟实际逻辑对不上。我一直想要一个工具能在开发当天就把代码理解掉然后把文档写到标准位置。项目里引过几个第三方文档插件效果一般原因是在 ABAP 对象模型面前通用文档工具的理解深度根本不够更别说直接调用 SAP 标准文档接口回写了。后来我认真研究了一下大模型在代码理解上的表现结论是LLM 在“读代码并生成结构化描述”这件事上已经超过了很多初级顾问。既然如此为什么不把它搬进 SAPZLLM 这个名字其实就是“Z 开头自定义对象 LLM”的意思按 SAP 开发者命名习惯客户自定义程序、类、表都用 Z 前缀一眼就能看出这是 ABAP 里自己做的 AI 工具。1.2 让 AI 自己写文档关键不是写而是“在哪写”很多人一听“AI 写文档”就想到外部网页、独立工具、复制粘贴回 SAP。但我的目标是彻底去掉这个“搬”的过程。我要的是 AI 直接在 SAP 标准入口工作也就是 SE80 对象浏览器、SE24 类构建器、SE38 编辑器这一套开发环境里输出文档并回写到标准文档位置。这里说的“标准入口”有两层意思。第一层是触发方式上不额外搞一个独立系统或者外部网页而是通过 SE80 里的自定义菜单项、事务码或者干脆在开发对象的工具栏上加一个入口让开发者随时可以调起 ZLLM。第二层更关键文档写回的目标必须走 SAP 标准机制。类文档写在类的 ABAPDoc 注释和方法描述里事务代码的标题写在 TSTCT 表里表字段的说明写在 DD02T/DD03T 里程序说明写在标准源码头注释里。这样团队成员打开 SE80 就能看到按 F1 也能查到不需要任何额外工具。在动手做之前我心里很清楚这个方案的边界LLM 生成的文档不能完全替代人工审阅尤其是涉及业务规则、法律合规、特定行业逻辑的说明。所以在设计里我坚持了一个原则——AI 生成初稿人工确认后再落库。工具负责把“写文档”这件事的启动成本压到最低但最终把关的还是人。后面的实现细节也是围绕着这条原则展开的。2. 整体架构与关键技术选型2.1 ABAP 怎么跟大模型通信一条 HTTP 请求的路要让 ABAP 调用大模型最直接的方式就是走 HTTP/HTTPS 调用 LLM API。虽然 SAP BTP 上有一些面向 AI 的集成方案但对于我这种主要跑在传统 ECC/S/4 环境里的项目最通用、最不依赖特定云平台的路径就是用 ABAP 自带的 HTTP Client 发请求。ABAP 里发 HTTP 请求的方式有几种IF_HTTP_CLIENT、CL_HTTP_CLIENT或者用更底层的 CALL METHOD。我最终选的是 CL_HTTP_CLIENT因为它支持设置 SSL、设置超时、处理响应状态码功能比较全而且代码写起来直观。基本调用链路是读取 API 配置URL、模型名、密钥引用→ 组装请求 JSON → 发送 POST 请求 → 接收响应 JSON → 解析返回内容。API Key 不能直接硬编码在代码里这是个底线。我用了一张自定义配置表 ZLLM_CONFIG存 API 基本信息如 URL、模型名、超时时间、最大 token 数。密钥本身不放明文而是放到 SM30 维护的视图里并且给这个视图加了授权对象控制只有少数管理员能看。在调用时通过配置表里的密钥标识去取值这样即使代码被传输到别的环境也不会把密钥带过去。从网络拓扑上看SAP 应用服务器要能访问外网的大模型 API。这一步在测试环境里通常没问题但生产环境往往有防火强控制需要提前跟网络团队确认出方向规则。我建议先在内网部署一套支持 OpenAI 兼容协议的模型服务用内网地址调用这样既避免公网延迟又更好控制数据外发范围。SAP 系统的数据合规是头等大事任何外呼都要有审批记录。2.2 为什么要把文档写回标准文档存储在设计 ZLLM 的过程中我曾经犹豫过一个点生成的文档到底是直接写进源代码注释还是同时更新 SAP 标准文档对象后来我决定两条腿走路但核心是“标准文档存储”。ABAPDoc 注释直接写进源码这是最下层的保障。IDE 和代码阅读器都会读取这些注释团队审查代码时也能直接看到。但如果只写代码注释覆盖场景太窄。比如一个事务代码的短文本说明、一个数据库表的字段含义、一个 BAPI 的参数解释这些并不存在于 ABAPDoc 里而是存储在 SAP 的文档表结构中。SE80 里右键对象查看“文档”读取的就是这些标准存储。所以我把 ZLLM 的文档回写目标分成了三类代码级程序源码头注释、类/方法的 ABAPDoc 注释。对象级事务代码短文本、类描述、函数模块描述。数据字典级表文本、字段文本、数据元素描述。对应到 SAP 标准表事务代码描述在 TSTCT表文本在 DD02T表长文本通过 SAVE_TEXT 维护但也涉及 TADIR 关联字段文本在 DD03T类描述在 SEOCLASSTX。如果用 SAP 的文档管理机制也可以通过 SAVE_TEXT 写到标准正文存储里。这里的关键不是背表名而是要理解SAP 的所有开发对象都挂在 TADIR 这个对象目录下要符合标准的文档生成方式必须走传输、激活、版本管理这些机制而不是直接 UPDATE 一张表。我采取的方案是对于源代码类对象使用 RPY_PROGRAM_UPDATE 或 SEO_CLASS_UPDATE 这类 Workbench 接口做更新这样可以正确触发激活和传输记录对于纯文本表如 TSTCT、DD02T、DD03T直接走对应的标准函数模块或更新视图而不是裸 UPDATE。这样生成的文档能跟着传输请求走换环境时不会丢。2.3 整体模块划分整个 ZLLM 工具我拆成了四个核心组件配置与权限表 ZLLM_CONFIG 存 API 参数事务码 ZLLM_DOC 做入口权限对象控制使用范围。上下文收集器根据传入的对象类型和对象名读取源码、属性、参数、现有注释组装成 LLM 可理解的上下文。LLM 网关负责 HTTP 调用、超时处理、重试、响应解析以及对不同模型 API 格式的兼容。文档写回器把 LLM 返回的内容分析成结构化文档片段选择 ABAPDoc 或标准文档接口写回。这个模块划分让我在调模型时不用同时改网络层在接不同大模型时也不用动写回逻辑。后面每次模型升级只需要调整提示词和 JSON 解析其他部分稳如磐石。3. 核心实现从源码输入到文档落库3.1 核心类 ZCL_LLM_DOC_GENERATOR 的设计实现部分我先做了一个核心类 ZCL_LLM_DOC_GENERATOR它是整个工具的发动机。这个类的关键方法不多但每个都承担了很明确的职责COLLECT_CONTEXT根据外部传入的对象类型和对象名从 SAP 资源库拉取源码和元数据把它转成一个结构性内表。BUILD_PROMPT把上下文数据和写死的提示词模板拼接成一个完整的请求体。CALL_LLM调用 HTTP 客户端把请求体发给大模型拿到返回文本。PARSE_RESPONSE把大模型返回的 JSON 解析成结构化文档内容。WRITE_DOC根据对象类型选择对应接口把文档写回。这里有一个设计要点COLLECT_CONTEXT 必须足够“贪婪”把对象相关的所有信息都收集起来包括源码、方法定义、参数定义、异常列表、描述字段甚至是同类对象的参考示例。因为 LLM 是一个无状态模型每次调用都必须自己提供足够的上下文否则它只能泛泛而谈。上下文数据结构我大致定义成这种形式types: begin of lty_obj_context, obj_type type trobjtype, obj_name type sobj_name, short_text type string, source type stringtab, methods type stringtab, params type stringtab, exceptions type stringtab, end of lty_obj_context.这段结构在类里定义成一个实例属性后面生成提示词和解析响应时都要复用。注意 source 字段用了 stringtab字符串内表因为 ABAP 源码行数多用字符串内表在拼接时效率更高也方便后续 ABAPDoc 的逐行写回。3.2 LLM 调用的代码实现HTTP 调用这层代码看起来不算复杂但坑不少。我先把最基础的一段请求代码贴出来method call_llm. data: lv_url type string, lv_request_body type string, lv_response type string, lv_status_code type i, lo_http_client type ref to if_http_client. lv_url https://your-llm-endpoint/v1/chat/completions. cl_http_clientcreate_by_url( exporting url lv_url importing client lo_http_client exceptions argument_not_found 1 plugin_not_active 2 internal_error 3 others 4 ). if sy-subrc 0. raise exception type zcx_llm_doc exporting textid zcx_llm_dochttp_create_failed. endif. 设置请求头 lo_http_client-request-set_method( if_http_requestco_method_post ). lo_http_client-request-set_header_field( name Content-Type value application/json ). lo_http_client-request-set_header_field( name Authorization value |Bearer { lv_api_key }| ). 设置请求体 lo_http_client-request-set_cdata( lv_request_body ). 发送请求 lo_http_client-send( exceptions http_communication_failure 1 http_invalid_state 2 http_processing_failed 3 others 4 ). if sy-subrc 0. raise exception type zcx_llm_doc exporting textid zcx_llm_dochttp_send_failed. endif. 接收响应 lo_http_client-receive( exceptions http_communication_failure 1 http_invalid_state 2 http_processing_failed 3 others 4 ). if sy-subrc 0. raise exception type zcx_llm_doc exporting textid zcx_llm_dochttp_receive_failed. endif. lv_status_code lo_http_client-response-get_status( ). lv_response lo_http_client-response-get_cdata( ). if lv_status_code 200. raise exception type zcx_llm_doc exporting textid zcx_llm_dochttp_non_200 msg lv_response. endif. endmethod.这段代码里有几个需要特别留意的地方。第一SSL 证书配置。如果你的 SAP 系统没法访问外网或者证书链不全do_http_client 会报 SSL 错误。解决办法是在 STRUST 里导入对应根证书或者在代码里指定 SSL 标识SSL_ID。第二超时时间。大模型推理耗时通常不短尤其是上下文长、生成内容多的时候。默认超时往往不够建议在 create_by_url 之后显式设置连接超时和读超时比如lo_http_client-propertytype_connect_timeout 30. lo_http_client-propertytype_read_timeout 120.第三响应的编码。很多 LLM API 返回 UTF-8 编码的中文内容如果服务器默认编码不是 UTF-8解析出来就是乱码。我在接收响应后强制做一次 UTF-8 转换call method cl_http_utilitydecode_utf8 exporting encoded lv_response receiving decoded lv_response.这一步看着小但实际运行中最常见的乱码问题就是这里埋的雷。3.3 提示词工程让模型高质量输出 ABAPDoc在 ABAP 场景里提示词工程比在其他语言里更需要刻意设计。原因很简单ABAP 对象模型复杂而且很多代码是“过程式 面向对象”混着写的模型如果只看到源码片段很容易生成泛泛的“这段代码用于实现某某功能”这种废话。我试了好几轮才整理出一套相对稳定的提示词结构。核心提示词大概长这样你是一位拥有15年经验的高级 SAP ABAP 开发顾问。 请根据下面提供的 ABAP 对象源代码和元数据完成以下文档生成任务 1. 判断对象类型类是类程序函数模块还是数据库表 2. 提取对象核心职责用2-3句中文说明这个对象在业务上的作用。 3. 生成 ABAPDoc 注释 - 如果是类生成类级别注释和方法级别注释 - 如果是程序生成程序头部注释 - 如果是函数模块生成函数模块说明。 4. 输出要求 - ABAPDoc 注释格式必须符合 SAP 规范 - 中文注释专业且简洁 - 不要修改原有代码逻辑 - 不要生成任何与业务合规、法律法规有关的内容。 以下是对象源代码 完整源码我特别加了“不要修改原有代码逻辑”和“不要生成任何与业务合规、法律法规有关的内容”这两条是有原因的。前者是为了避免 LLM 在输出注释时附带“建议修改代码”之类的内容干扰开发者的判断后者是因为 SAP 项目经常涉及企业敏感业务模型生成内容里如果夹带不恰当的表述容易引出合规问题。在提示词里限制是最省钱、最直接的防线。在输出格式上我自己设计了一个固定的 JSON 结构而不是让模型自由发挥。这样做的好处是解析稳定。我给模型的输出约束是{ object_type: CLASS, object_name: ZCL_XXX, short_description: 一句话说明, long_description: 2-3段详细说明, abap_doc_lines: [ ! p class\shorttext\类说明/p, ! 详细说明..., ! author AI, ! since 2025-01-01 ], method_docs: [ { method_name: METHOD_A, abap_doc: ! p class\shorttext\方法说明/p } ] }为了让模型稳定输出这个 JSON我在提示词里加入了“只输出 JSON不要输出任何解释文字”的强调。如果不加强制模型偶尔会在 JSON 前输出“好的下面是我生成的文档”这类废话解析的时候还得手工剥离。加上强制约束后我再用 /ui2/cl_json 直接解析省去不少麻烦。3.4 文档写入的落地细节写完提示词和模型调用接下来是最后也是最重要的环节把生成的文档写回 SAP。这里我分对象类型走了两条路径。对于类和方法我用 SEO_CLASS_UPDATE 更新类描述并把生成的 ABAPDoc 注释写入类池源码对于程序和函数组我用 RPY_PROGRAM_UPDATE 更新源码。为什么非要用这些 Workbench 接口而不是直接改数据库表因为只有走这些接口SAP 才知道对象被改动才会触发 Transport Request、激活、版本管理。直接 UPDATE 表虽然也能改数据但会绕过系统的一致性检查风险太大了。一个我踩过的坑是直接修改源码行会导致 ABAP 对象的“不可激活”状态。如果开发者当前已经打开了同一对象并且还没保存自己的修改ZLLM 写入的新版本可能跟工作区里的内容冲突。所以我加了锁检查写入之前尝试用 ENQUEUE_E_TABLE 或对象级锁去锁定对象如果锁不到就明确提示“请先关闭该对象在SE80里的编辑会话”。写 ABAPDoc 注释到源码时还要注意位置。类级别注释要放在 CLASS 定义的声明部分之前通常是CLASS zcl_xxx DEFINITION上一行方法注释要放在方法的METHODS声明或者方法实现的开始位置。我是在读源码时先按关键字定位再用一个位置标记变量记录插入点。这个逻辑代码不算复杂但却是最容易出 bug 的地方——插入位置差一行ABAPDoc 就跟方法对不上号了。4. 把功能做成 SE80 里能随手调起的入口4.1 事务码、权限和参数维护把功能做成事务码是第一步。我在 SE93 里创建了一个事务码 ZLLM_DOC启动对象选择“程序 屏幕”然后指定主程序。这个事务码的作用是进入一个简单选择界面允许手动输入对象类型和对象名也可以在 SE80 中通过参数传递的方式直接跳转。权限控制方面我创建了一个自定义权限对象 Z_LLM_DOC包含 ACTVT 和对象名范围字段。只有拥有 S_DEVELOP 并且被授予 Z_LLM_DOC 权限的开发人员才能运行生成功能。这样防止非开发人员在生产系统里乱触发外部 API 调用也方便审计。配置表 ZLLM_CONFIG 我做了 SM30 维护视图字段包括配置标识、API_URL、MODEL_NAME、API_KEY、TIMEOUT、MAX_TOKENS。同时加了个 LOG 开关开启后每次调用都会写入日志表 ZLLM_LOG方便排查问题和统计 token 消耗。4.2 三种接入 SE80 的方式真正的挑战是让 ZLLM 出现在“标准入口”里而不是让开发者每次都要先输入事务码。我试了三种接入方式复杂度递增体验也递增。第一种最省事把事务码 ZLLM_DOC 放到开发者的个人收藏夹里同时在 SE80 的右键菜单里通过“外部工具”添加一个启动项。这种方式不改任何标准对象安全性最高适合刚上线时小范围试用。第二种是修改 SE80 相关 GUI 状态在工具栏加一个按钮。这需要改标准程序或者做增强。SE80 的主程序是 RS_OBJECT_TREE工具栏的状态码比较复杂直接改标准 GUI 状态在升级时有被覆盖的风险。更稳妥的方式是用隐式增强挂一段代码动态添加按钮并关联到动作码。但这里有个麻烦SE80 是树形控件点击的对象类型和名称要能传出来。我通过读取当前选中的对象节点来获取实现上需要动点 EVENT 处理的脑筋。第三种是我个人最推荐的方式用事务码直接接收参数再从 SE80 的对象列表里定义一条“外部程序关联”。其实从 ABAP 开发者的习惯来看真正高频写文档的场景不是“在 SE80 里选中类再点按钮”而是在代码写完后自然想到“我得补文档了”。所以我把入口设计成在事务码里输入对象名甚至可以在 SE38 的初始界面右键“运行外部工具”输入 ZLLM_DOC 后自动带上当前程序名。接入这块我的建议是别追求一步到位先把事务码方案跑顺畅团队成员养成“写完代码顺手生成文档”的习惯再考虑做更深的界面增强。深层 GUI 修改的收益在开头并不明显反而会增加升级维护成本。4.3 运行参数与实际效果当我在 SE80 里选中一个类 ZCL_MATERIAL_HELPER然后调用 ZLLM_DOC工具会依次做这几件事读取类的方法列表和方法源码读取类的短描述、包名、原始系统中的传输信息把类名和包名信息拼接到提示词里调用大模型生成类说明和方法 ABAPDoc在预览界面展示生成结果支持逐段确认或修改确认后写回 SAP 标准位置。预览环节非常重要。我见过很多 AI 辅助工具是“生成即写入”完全不给人把关机会。但在 SAP 这种严谨环境里AI 生成的内容必须先过目。我做成类似“审批”的界面左边是原始源码右边是生成的 ABAPDoc 和对象说明开发者可以逐段勾选是否采纳也可以直接编辑右边的内容。确认后勾选的内容才会被写回。这样既保留了 AI 的效率也保证了最终入库文档是开发者认可过的。实际运行下来一个 2000 行左右的类完整生成到确认写库大约耗时 3 到 5 分钟。大部分时间花在模型推理上SAP 本身的读写很快。对比手工写同样的文档至少要 30 分钟到 1 小时这个效率提升是非常明显的。5. 实测与踩坑实录5.1 通信层的坑SSL、代理与超时第一个坑就是 SSL 证书。系统报 SSL_ERROR_SSL排查了半天发现 SAP 服务器的证书库STRUST里缺少我所调用的 LLM API 的根证书。解决方案是把 API 域名对应的根证书导入 STRUST然后在调用时指定 SSL ID。因为我们的 SAP 系统在内外网之间有防火墙和代理我还在 SM30 里维护了代理服务器地址。需要注意的是SAP 的 HTTP Client 对代理的支持并不总是那么直观有时候还要设置 NO_PROXY 来跳过内网地址否则请求会被代理拦下来。超时问题也很突出。默认的 HTTP 请求超时通常只有几十秒但 LLM 生成上千字文档时响应时间很容易超过 60 秒。我在配置表里把超时单独拆出来放在 ZLLM_CONFIG 的 TIMEOUT 字段里每次请求前动态设置。这样遇到不同模型时可以单独调不用改代码。5.2 JSON 解析与中文乱码的坑JSON 解析的坑主要出在两个地方。第一模型偶尔会返回不合法 JSON多了一个逗号或者引号没闭合/ui2/cl_json 直接报解析错误。解决办法是在解析前做一次“提取 JSON 片段”的预处理用正则找到{开始到最后一个}结束的字符串截出来再解析。虽然这个方法听起来暴力但在生成内容里包含大量 ABAP 代码时模型输出很容易夹带源码片段截取大括号可以最大限度减小干扰。第二中文编码。我在前面提过用 CL_HTTP_UTILITYDECODE_UTF8 做转换。这个坑在开发机上是 UTF-8 编码时不会暴露一部署到非 Unicode 系统就炸了。如果你们的系统还是老的非 Unicode 架构建议尽早评估迁移 Unicode否则中文字符在 HTTP 传输和写回标准表时都很容易出问题。5.3 性能与并发控制ZLLM 调用大模型是重量级操作不能像普通报表一样让人随便狂点。我做过一次并发压力测试10 个开发者同时点击生成外部的 API 网关直接触发了限流策略后面几个请求全部报 429。这个问题的解决思路是全面控制并发在 ZLLM_CONFIG 里加了一个 MAX_CONCURRENT 参数在每次调用前用 SAP 锁机制做并发计数超过上限时直接提示“当前并发已满请稍后重试”。同时在后台上做异步处理生成任务提交到 SM36 的后台作业完成后通过 spool 或消息通知开发者。另一个性能注意点是源码长度。一个大类的完整源码可能有近万行全量塞进提示词不仅浪费 token还可能超过模型输入上限。我做了分段策略方法级别的 ABAPDoc 生成只取该方法的源码不取整个类类级别说明则只取方法签名和关键字段不取全部方法体。这个“按需取上下文”的小优化直接把单次调用的 token 消耗降低了 40%。5.4 文档质量的反复调优模型生成文档的质量是整件事成败的关键。我一开始用最朴素的提示词“生成这个类的ABAPDoc”结果生成的内容特别虚全是“该类提供了相关功能”这种废话。后来我在提示词里加入了“基于代码具体实现描述方法间调用关系”质量立刻上了一个档次。还有一个经验是开发语言规范很重要。ABAP 代码里如果一个方法叫 GET_PRICE模型能猜到是取价格但如果方法名是 DO_IT_001模型就只能靠猜。这里我没有把锅都甩给模型而是在提示词里要求“如果方法名和参数名不规范请给出简化说明但不要臆造业务含义”。这一步很关键它把 AI 的“想象空间”框住避免生成看似合理实则错误的内容。我整理了一张文档质量检查清单写回之前自动过一遍文档是否包含对象名和对象类型ABAPDoc 行是否以 ! 开头是否包含未证伪的业务假设是否有模型自己编造的方法名或参数名是否包含与代码逻辑明显矛盾的描述其中第四项是重点。模型在生成方法说明时偶尔会“脑补”出源码里不存在的方法名这在人工审阅时容易一眼带过。我把检查逻辑写成 ABAP 代码逐行比对生成文档里出现的方法名是否都在源码中定义过不一致就标记为“需人工确认”。这个自动检查弥补了 LLM 最大的短板——幻觉。5.5 典型问题速查表问题现象可能原因解决办法调用时报 SSL 错误服务器证书库缺根证书在 STRUST 导入 API 域名根证书指定 SSL ID返回内容中文乱码非 Unicode 系统或未做 UTF-8 转换用 CL_HTTP_UTILITYDECODE_UTF8 预处理请求响应超时默认超时过短在配置表单独维护超时时间动态设置返回 JSON 无法解析模型输出了多余内容用正则截取 JSON 片段再调用 /ui2/cl_json生成文档里的方法名不存在LLM 幻觉脑补方法写回前自动比对源码方法清单标记可疑项写回文档后对象处于不可激活状态与其他会话冲突写回前先做对象锁检查冲突时明确提示多个开发者同时调用被限流外部 API 有并发限制加并发锁超限时提示稍后重试支持后台异步类池源码里 ABAPDoc 插入位置错乱插入点定位逻辑问题增加关键字定位和单元测试覆盖多种嵌套场景6. 最后想说的经验如果让我总结这个 ZLLM 项目里最重要的经验我会说这么几条。第一AI 工具在 SAP 里落地最大的阻力不是技术而是团队的使用习惯。工具做得再好如果开发者没有“写完代码就顺手生成文档”的意识最后还是会被闲置。我后来做了个小改动在代码激活检查里加了一个提示当检测到方法没有 ABAPDoc 注释时在激活日志里给出“可通过 ZLLM_DOC 生成文档”的提示。这个看似不起眼的改动反而比任何培训都管用。第二AI 生成的文档适合做初稿不适合做终稿。我对生成内容加了人工确认环节一开始团队觉得麻烦但运行两周后大家认可了这种模式。因为模型生成的初稿质量已经很高人工确认主要是改一下业务术语、补一点项目里约定俗成的缩写而已。这个流程比从零写省了太多力气。第三大模型的选择要预留切换空间。我最初接的是公网大模型 API后来集团要求数据不出内网我就在内网部署了一款兼容 OpenAI 协议的服务。由于 ZLLM 的 LLM 网关层做了抽象提示词和解析逻辑完全复用切换只改了配置文件。如果你也准备做类似工具一定要在架构上把模型调用层隔离开不要和 SAP 业务代码强耦合。后续我打算在 ZLLM 的基础上继续扩展两个方向一个是让 AI 能根据代码变更自动维护文档差异而不是每次全量重新生成另一个是把文档生成和代码 review 流程打通在 review 环节自动提示“这段代码的文档已经过期”。这些方向都基于同一个核心思路AI 不是替人思考而是把重复劳动消化掉让人把精力放在真正需要业务判断的地方。这个思路在 SAP 的任何一个技术模块里都适用。