1. 项目概述与方案选型

1.1 这个项目解决什么问题

先说说背景。很多企业上了SAP之后,业务数据确实都收拢集中了,但问题也来了——业务人员想查个库存、想看看订单状态,还得学事务代码、记各种报表路径。财务月底想跑个报表,IT部门排队排到天荒地老。而另一边,AI大模型已经卷到飞起,Codex、WorkBuddy、豆包这些工具一个比一个能聊,能不能让它们直接跟SAP对话,帮业务人员把数据查出来?

这个项目做的事情很简单: 把AI助手接到SAP系统上,让用户用自然语言问问题,AI通过SAP的接口去查数据、执行操作,再把结果翻译成人话返回给用户。 说白了,就是给SAP装上一个"会说人话的前台"。

我实测下来,Codex、WorkBuddy、豆包这三个都能跑通,只是接入方式各有取舍。后面我会把每种方案的配置细节、踩坑点都写清楚。

1.2 方案选型:RFC、BAPI还是OData

连接SAP的方案,市面上主流的就三条路:

  • RFC/BAPI :SAP的老牌接口方式,稳定、功能全,但需要从ABAP侧编写函数,配置比较重,适合企业内部高权限场景。
  • OData服务 :SAP Gateway(网关)的标准姿势,配置相对轻量,权限可控性好,适合对外开放或者接第三方平台。
  • 直连数据库 :最粗暴的方式,直接把SAP底层的HANA或者Oracle表暴露出来让AI读。这种方式我极度不推荐在生产环境用——绕过业务逻辑直接读数据,脏数据、权限失控、锁表,哪个坑都能让你加班到怀疑人生。

我的建议是: 如果是企业内部项目,优先走OData服务;如果涉及大量自定义业务逻辑,老老实实封装BAPI。 两者都支持HTTP调用,AI平台接入最顺滑。

1.3 适合谁来参考

这篇文章适合三类人:

  • SAP Basis/ABAP开发 :负责SAP端的接口搭建、权限配置,可以直接照抄配置步骤。
  • 企业架构/数据团队 :想搞"AI+ERP"场景,需要了解方案选型和落地路径。
  • AI应用开发者 :手里有Codex、豆包这类AI平台,想接企业数据源,可以参考集成模式。

如果你是这三类之外的读者,也没关系,文章里的思路和踩坑经验是通用的—— 任何AI接业务系统的项目,核心逻辑都差不多:接口怎么暴露、权限怎么控制、上下文怎么管理。

2. SAP端接口准备:AI连接的地基

2.1 OData服务创建全流程

要让AI稳定地连上SAP,地基必须打牢。我用的是SAP Gateway(事务代码SEGW)创建OData服务的方式。大体流程如下:

第一步:定义数据模型

在SEGW里创建一个新项目,定义实体类型(Entity Type)和实体集合(Entity Set)。比如我要暴露一个"库存查询"服务,就定义Material(物料)、Plant(工厂)、Stock(库存数量)这几个字段。这里要注意字段命名规范和类型选择,后面AI解析参数是否顺畅,很大程度上取决于这一步。

第二步:生成运行时对象

定义好模型后,直接生成运行时对象,会自动创建出DPC(Data Provider Class)和MPC(Model Provider Class)两个类。我们需要在DPC的 GET_ENTITYSET 方法里写数据查询逻辑,调用底层的BAPI或者直接读视图。

第三步:注册服务并激活

在 /IWFND/MAINT_SERVICE 事务代码里添加这个服务,勾选"系统别名"(比如 LOCAL 代表当前系统),激活即可。激活后可以用 /IWFND/GW_CLIENT 测试,确认返回的JSON/XML格式正确。

这里分享一个我的实测经验: OData服务暴露的字段一定不要图省事把整张表全拖上去,只暴露AI需要的最小字段集。 原因有两个:

  • 数据越少,AI的token消耗越低,响应越快;
  • 安全边界更清晰,AI能查什么不能查什么,在数据模型层就卡死了。

2.2 创建核心数据服务:生产订单状态查询

以我实测的"生产订单状态查询"为例,完整配置步骤如下:

数据模型定义(MPC类关键代码):

METHOD define.
  DATA: lo_entity_type TYPE REF TO /iwbep/if_mgw_odata_entity_type.
  
  " 创建实体的主键属性
  lo_entity_type = model->create_entity_type(
    iv_entity_type_name = 'ProductionOrder'
    iv_source_entity_set_name = 'OrderSet'
  ).
  
  " 添加字段
  lo_entity_type->create_property(
    EXPORTING
      iv_property_name = 'OrderNo'
      iv_is_key = abap_true
      iv_ordertype = 'Edm.String'
  ).
  
  lo_entity_type->create_property(
    EXPORTING
      iv_property_name = 'Status'
      iv_ordertype = 'Edm.String'
  ).
  
  lo_entity_type->create_property(
    EXPORTING
      iv_property_name = 'PlannedQty'
      iv_ordertype = 'Edm.Double'
  ).
ENDMETHOD.

数据获取逻辑(DPC类关键代码):

METHOD GET_ENTITYSET.
  " 调用标准BAPI读取生产订单信息
  CALL FUNCTION 'BAPI_PRODORD_GET_LIST'
    EXPORTING
      iv_order_number = iv_order_no
    IMPORTING
      et_orders = lt_orders.
  
  " 将BAPI返回结构转换为OData输出格式
  LOOP AT lt_orders INTO ls_order.
    APPEND INITIAL LINE TO et_entityset ASSIGNING FIELD-SYMBOL(<fs_entity>).
    <fs_entity>-orderno = ls_order-order_number.
    <fs_entity>-status = ls_order-order_status.
    <fs_entity>-plannedqty = ls_order-planned_quantity.
  ENDLOOP.
ENDMETHOD.

这一步的 关键点 是:BAPI返回的数据结构往往是嵌套的、有多个层级的,必须在此处做好"压平"处理,转换成flat的实体结构。否则后面AI平台解析时会出各种奇怪的问题,最常见的就是"字段存在但取不到值"。

2.3 OAuth 2.0权限配置

SAP系统内部有权限对象(PFCG),但AI平台通过OData调用时,走的是OAuth层面的授权。我建议用SAP Gateway的OAuth 2.0配置(事务代码 /IWFND/IWSG ):

  1. 创建OAuth客户端ID,绑定到具体的通信用户。
  2. 指定授权范围(Scope), 精细到服务级别 。比如 ai_inventory_query 只能查库存服务, ai_order_query 只能查订单服务,严禁用一个万能Scope。
  3. 设置Token过期时间,默认3600秒,按需调整。

实际踩过的坑 :AI平台调用时,OAuth的Token端点(Token Endpoint)需要从SAP的 /IWFND/CLIENT_REGISTRY 里拿准确的URL,这个URL格式因SAP版本不同有差异。我一开始对接WorkBuddy时,Token端点少写了一层路径,导致每次调用都401。最后抓包对比发现是 sap 这个路径段的问题。

安全提示 :日常运维中,OAuth客户端密码要至少90天轮换一次,并且严禁把客户端密钥硬编码在AI平台的提示词、代码或公共配置里。一旦泄露,等于把SAP的数据接口大门钥匙交给了别人。

3. AI平台接入实操:Codex、WorkBuddy、豆包

3.1 Codex接入SAP

Codex是OpenAI推出的编程智能体,支持Assistant API,可以定义tools(工具),让模型自主决定何时调用外部函数。把SAP的OData服务封装成一个tool,是Codex接入的标准做法。

核心配置(Python示例):

from openai import OpenAI
import requests
import json

client = OpenAI(api_key="your_api_key")

# 定义SAP查询工具
tools = [
    {
        "type": "function",
        "function": {
            "name": "query_sap_inventory",
            "description": "查询SAP系统中的物料库存情况。当用户询问库存、物料数量、可用量等问题时调用此工具。",
            "parameters": {
                "type": "object",
                "properties": {
                    "material": {"type": "string", "description": "物料编号,如1000-0012"},
                    "plant": {"type": "string", "description": "工厂代码,如1000"}
                },
                "required": ["material", "plant"]
            }
        }
    }
]

def call_sap_odata(material, plant):
    """通过OData服务查询SAP库存"""
    url = f"https://sap-gateway.example.com/sap/opu/odata/sap/ZAI_INVENTORY_SRV/InventorySet"
    params = {"$filter": f"material eq '{material}' and plant eq '{plant}'"}
    headers = {"Authorization": "Bearer " + get_sap_token()}
    
    resp = requests.get(url, params=params, headers=headers, verify=False)
    return resp.json()

# 对话主循环
def chat_with_sap(user_message):
    messages = [{"role": "user", "content": user_message}]
    
    response = client.chat.completions.create(
        model="gpt-4-turbo",
        messages=messages,
        tools=tools,
        tool_choice="auto"
    )
    
    # 若模型决定调用工具
    if response.choices[0].message.tool_calls:
        tool_call = response.choices[0].message.tool_calls[0]
        args = json.loads(tool_call.function.arguments)
        sap_result = call_sap_odata(args["material"], args["plant"])
        
        # 将结果回传给模型生成自然语言回复
        messages.append(response.choices[0].message)
        messages.append({
            "role": "tool",
            "content": json.dumps(sap_result),
            "tool_call_id": tool_call.id
        })
        final_response = client.chat.completions.create(
            model="gpt-4-turbo",
            messages=messages,
            tools=tools
        )
        return final_response.choices[0].message.content
    
    return response.choices[0].message.content

Codex接入的关键经验 :

  • 工具描述写得越细,模型越不容易选错工具。 我一开始的description只写了一句"query SAP inventory",结果模型经常在用户问订单状态时也去调库存接口。后来把每个工具描述写成"当用户提到xxx关键词/在xxx场景下调用"的格式,准确率显著提升。
  • SAP返回的数据往往包含大量字段,但一次对话模型只需要其中几个。 我建议在工具返回前,先做字段裁剪,只保留用户问题相关的字段,减少token消耗,也给模型减负。
  • 模型输出的工具参数格式偶尔会不标准。 比如物料编号中间有零散的空格、引号,Codex偶尔会忘记转义。我加了参数清洗环节,对字符串参数做strip和格式化校验,问题基本消除。

3.2 WorkBuddy接入SAP

WorkBuddy走的是另一种路线——它本身就是一个"智能体编排平台",提供了可视化的Workflow配置界面,不需要像Codex那样写主循环代码。如果你公司里用的AI平台是WorkBuddy或其他类似的智能体平台,接入SAP的完整配置逻辑是:

  1. 创建自定义API节点 :在Workflow里添加一个HTTP Request节点,Method选择GET,URL填OData服务的查询端点。
  2. 配置鉴权 :WorkBuddy支持OAuth 2.0 client credentials模式,把SAP Gateway申请的Client ID和Client Secret填进去,指定Token URL即可。这一步配置正确后,WorkBuddy会自动处理Token的获取和刷新。
  3. 定义输入输出参数 :明确这个API节点的Input参数(比如物料号、工厂),Output参数(比如库存数量、可用量),后续AI对话流程就可以引用这些参数。
  4. 将节点接入对话流程 :把API节点挂到意图节点(Intent Node)后面,当用户触发"查库存"意图时,WorkBuddy自动执行API调用,并把结构化结果传给大模型生成回答。

与Codex方案的对比 :

对比维度 Codex方案 WorkBuddy方案
配置方式 代码实现 可视化编排
灵活性 高,可任意改造 中等,受平台能力限制
上手难度 需一定编程能力 业务人员可上手
适合场景 深度定制、复杂逻辑 标准化流程、快速落地

3.3 豆包接入SAP

豆包给了另一种选择:它提供了Function Calling的API,与Codex的tools机制类似,但在国内网络环境下部署更方便,适合企业内部部署私有化版本。

豆包接入SAP时,我推荐用"先工具后对话"的架构:

用户输入 → 豆包识别意图 → 调用SAP接口函数 → 获取JSON结果 → 返回自然语言

这里涉及两层开发:

  • SAP侧的"函数注册" :把OData服务封装成一个可以被Function Calling调用的OpenAPI Schema。豆包的控制台支持直接导入OpenAPI文件,我建议在导出时生成标准的OpenAPI 3.0格式,字段命名保持和SAP OData一致,减少映射转换。
  • 业务侧的"执行逻辑" :Function Calling被触发后,后端接收到参数,组装OData请求并执行,把结果回传给豆包。这里有个细节:豆包对Function返回的结果格式要求相对宽松,JSON即可,但必须严格保证字段名和Schema一致。

实测注意点 :豆包的Function Calling对参数上限有约束,SAP的筛选条件如果特别复杂,建议拆分多个函数。比如"查库存"一个函数、"查订单"一个函数,不要尝试在一个函数里把整个SAP业务逻辑都塞进去。

3.4 三种接入方式对比总结

对比项 Codex WorkBuddy 豆包
接入方式 API编程 可视化Workflow Function Calling
核心依赖 OpenAI API Key 平台订阅 豆包API Key
部署位置 海外/国内均可 按平台 国内友好
主要优势 灵活、可控性强 低代码、快速搭建 网络稳定、中文理解好
注意风险 Token成本高 灵活性受限 大型参数兼容性待验证

我的最终建议 :如果技术团队底子好, 无脑选Codex ,它最大的价值是可以用代码完全掌控整个交互链路——从参数清洗到结果格式化,再到多轮对话中的上下文管理,都能做到极致。如果速度优先、业务迭代快, WorkBuddy 可视化编排能省一半工作量。如果要求数据合规不出境, 豆包私有化 部署是唯一选择。

4. 实操过程与核心环节实现

4.1 端到端联调流程

整个"AI连接SAP"的联调,我把它拆成6个环节,每个环节都有独立的验证方法:

环节一:SAP OData服务可访问性测试

这是最基础的一步。直接用浏览器或Postman访问OData端点的metadata,能返回XML格式的 $metadata 文档就说明服务已暴露且可访问。

GET https://<SAP-Gateway>/sap/opu/odata/sap/ZAI_INVENTORY_SRV/$metadata

注意:URL里的 sap/opu/odata/sap/ 是SAP Gateway的标准路由前缀,不同的SAP系统(比如S/4HANA和ECC)会有些许差异,但基本都是这个模式。

环节二:OAuth Token获取验证

在Postman里配置OAuth 2.0 client credentials授权,测试能否拿到Token。能拿到,说明用户、密码、权限范围都是通的。拿不到,优先检查配置好的用户是否分配了足够的PFCG角色。

环节三:AI平台API连通性测试

这一步是指AI平台本身的API Key是否有效。Codex、豆包直接调用对话接口测试,WorkBuddy则测试工作流是否能正常触发。

环节四:AI到SAP的穿透测试

让AI自然语言生成调用参数,再通过它调SAP接口。我建议先问一个非常标准的场景化问题,比如"帮我查一下物料1000-0012在工厂1000的库存",看链路是否完整通。

环节五:异常场景模拟

这是最考验稳定性的环节。故意输入不规范的问题,比如"查一下那个库存"——AI可能会生成不完整的参数,此时后端要有兜底逻辑(比如返回提示"请提供物料编号")。还应该测试SAP宕机或超时的情况,AI能不能给用户一个友好的提示而不是直接报错。

环节六:性能压测

模拟多用户同时通过AI查询SAP,观察SAP Gateway的负载情况和AI平台的响应耗时。这一步往往能暴露 慢查询 问题——SAP的OData服务如果没加好索引,AI场景下每个请求都要全表扫描,性能会很难看。

4.2 上下文管理与多轮对话优化

AI接SAP和多轮对话场景下,一个容易被忽略的问题是 上下文管理 。用户说"查完这个库存,再帮我看看它的订单情况"——这里的"它"指的是之前查询的物料,而AI本身是不知道这个"它"具体是什么的。

建议做法是:

  1. 在后端保存会话状态 ,维护一个"当前物料"、"当前工厂"的临时变量,每次对话轮次都更新。
  2. 在工具调用的参数生成阶段 ,向前追溯最近几轮对话,把省略掉的指代补充完整。
  3. 在AI的System Prompt里明确说明 :"当用户使用'它'、'这个'等代词时,结合上下文历史来判断具体指代对象。"

这个方法实测下来能显著提升多轮对话的准确率。我开发的时候花了一整天在Prompt上下功夫,最后把"指代理解"逻辑写死在Prompt里,效果比完全依赖模型自我推理好得多。

4.3 数据权限与越权防护

企业里最怕的不是AI不会干活,而是AI乱干活——比如一个普通业务员直接问"全公司所有物料的库存",如果OData的筛选条件没限制死,AI就会把所有数据拉出来。

我的做法是 在SAP OData服务层面强制用户维度过滤 :

METHOD GET_ENTITYSET.
  " 从OAuth Token中解析当前用户信息
  CALL METHOD /iwbep/cl_mgw_util=>get_user_from_token
    IMPORTING
      ev_user = lv_user.
  
  " 根据用户权限范围,强制追加过滤条件
  SELECT ...
    FROM marc
    WHERE werks IN (SELECT werks FROM z_user_auth WHERE uname = lv_user).
ENDMETHOD.

这样无论AI怎么发挥,SAP服务端都只会返回该用户权限范围内的数据。

4.4 日志追踪与审计

AI操作SAP的每一步都应该留下完整的审计日志。日志最少要包含四个要素:

  • 会话ID :哪一次对话触发的操作
  • 用户ID :谁问的这个问题
  • 参数快照 :AI生成的完整参数(含未清洗前的原始值)
  • SAP响应时间 :SAP侧处理耗时,排查慢查询必备

日志存哪?我建议写回SAP应用日志(事务代码SLG0/SLG1),统一纳入企业的日志监控体系,方便和SAP原生事务做关联分析。生产环境排查问题的时候,这套日志体系能节约一半时间。

5. 常见问题与排查技巧实录

5.1 认证与权限类问题

问题现象 可能原因 排查方法与解决方案
每次调用都返回401 OAuth的Token URL拼写有误 核对SAP Gateway的Token端点,注意 sap 路径段
返回403 Forbidden 通信用户的PFCG角色缺少权限 在SU01中给用户分配对应角色,重新生成Token
Token能获取但OData数据空白 权限范围未精细到服务 在OAuth客户端里授权具体的Scope,而不是用默认全量

真实踩坑记录 :我曾在Codex接入时遇到一个诡异问题——Postman测试OData能通,Codex调用却一直401。排查了半天,发现是Codex的HTTP库在发送Token时,把Bearer前缀的格式搞错了,多了一个空格。加了个Header格式化中间件后问题解决。 工具不能全信,遇到问题先用curl裸调一遍,能排除很多"灵异事件"。

5.2 数据格式与解析类问题

SAP返回的数据结构和AI模型的预期差异,是另一个高频雷区。

  • SAP OData的日期格式是 /Date(1700000000000)/ ,这种格式AI一般不认。需要在后端统一转换成ISO 8601格式,我在实现中对所有DateTime类型字段做了转换封装。
  • SAP的十进制数在JSON里可能是字符串 ,比如 "12.50" 。如果不处理,AI模型可能在求和、比较时把它当文本,算出来的结果完全跑偏。我在后端把所有数值字段统一 parseFloat 处理。
  • 字段名大小写 :SAP OData默认是PascalCase或者全大写,AI模型的训练数据里更习惯camelCase和snake_case。这里有个取舍:是改SAP侧的属性名还是让AI去适应?我建议在AI平台侧的映射层转换,不要动SAP原生属性名,否则影响其他依赖该OData服务的系统。

5.3 性能与超时类问题

实测下来,AI接SAP最大的痛点是 RTT(往返时间)太长 :AI生成参数要几秒,SAP查询要几秒,AI再生成自然语言又几秒。用户等一个回答可能要15秒以上,体验很糟。

优化方案有三个层面:

  1. SAP侧加缓层 :对高频查询(如物料库存)增加结果缓存,设置的TTL根据业务实时性要求来定,我一般设5分钟。
  2. AI侧精简输出 :限制模型生成的回复长度,比如设置 max_tokens ,让回答更简洁生成的耗时也会缩短。
  3. 异步任务化 :对耗时长的复杂报表类查询,走异步任务——AI先回复"正在查询,预计10秒完成",后台SAP查询完成后推送给用户。实测这种设计在"AI接SAP"的场景里非常实用,用户感知的等待时间大幅缩短。

5.4 排查工具推荐

  • SAP Gateway Client (事务代码 /IWFND/GW_CLIENT ):调试OData服务必备,能直接看到完整的请求/响应报文。
  • SWA(SAP Web Application Server日志) :SAP后端报错的第一现场。
  • AI平台API调试器 :Codex和豆包的调试面板,能查每次Function Calling的prompt和tool call记录。
  • Charles/Fiddler抓包 :当怀疑是中间网络策略或代理拦截时,用抓包工具看完整的HTTP链路。

6. 安全加固与生产落地

6.1 传输层安全策略

AI平台和SAP Gateway之间所有的HTTP通信, 必须走HTTPS 。这只是底线,更重要的策略是:

  • IP白名单限制 :在生产环境,SAP Gateway的防火墙规则只放行AI平台出口的固定IP段。
  • TLS版本限制 :关闭TLS 1.0/1.1,强制使用TLS 1.2+,避免中间人攻击。
  • 内网隔离 :如果AI平台和SAP都在内网,可以考虑跳过外网路径,直接内部域名访问,减少暴露面。

6.2 数据脱敏与敏感字段过滤

AI对话场景下,数据脱敏尤其要重视。SAP的主数据中混有大量敏感信息:客户手机号、银行账号、员工薪资、销售成本。我在OData服务层做了字段级脱敏:

" 在DPC类中,对敏感字段做标记替换
CASE ls_entity-field_name.
  WHEN 'BANK_ACCOUNT' OR 'PHONE_NUMBER'.
    ls_entity-field_value = '***'.
ENDCASE.

实测中,这个方案比在AI平台的Prompt里写"不要输出敏感信息"有效得多—— 从源头切断,而非依靠模型自觉 。

6.3 监控与告警体系

生产环境上线后,我建议至少配置四个监控指标:

  • AI调用SAP的失败率 :连续5分钟超过10%,立刻告警。
  • OData服务平均响应时间 :超过1秒的慢查询,需要优化索引或加缓存。
  • Token消耗突发增长 :不明原因的Token消耗激增,可能是Prompt结构异常或SAP返回了超大响应体。
  • 异常参数访问模式 :比如同一AI账号在短时间内大量查询不同物料,可能说明存在恶意遍历或越权尝试。

这些指标都可以通过SAP Solution Manager或外部监控平台(Prometheus+Grafana)采集。 宁可监控报警多也不要少,AI接入SAP后问题的放大效应非常明显——一个小配置错误可能瞬间扫全表。

6.4 日常运维注意事项

最后整理几条我自己运维过程中踩坑总结出的注意事项:

  1. SAP系统升级后,务必重新验证OData服务 。SAP Note的更新经常影响Gateway框架,尤其版本升级后接口签名可能有细微变化。
  2. AI平台的模型版本升级后,要做回归测试 。我之前遇到过一次豆包升级,原本正常的Function Calling参数解析变得不稳定,花了整整一天排查才定位到是模型版本导致的。
  3. 通信用户的密码变更必须及时同步到AI平台 。这里建议用一个密钥管理服务(比如Vault),避免在多个配置文件里手工更新。
  4. 定期检查OAuth Token的Scope 。业务变更后Scope可能会需要调整,但顺手清理废弃Scope的习惯一定要有,否则权限越积越多。

7. 结尾心得

这套"AI + SAP"的配置方案,我从前期的方案选型到最后的生产上线,前后花了三周。

坦白说,技术本身并不复杂——OData、OAuth、Function Calling,都是各个领域相对成熟的东西。真正的难度在于 跨领域思维 :你需要懂SAP的权限模型和BAPI规范,还要懂AI平台的工具调用机制和上下文管理,更要在两者之间找到那个最合适的切入点。

我个人最大的体会是: 别指望AI靠一个"万能提示词"就能自动搞定SAP的所有业务。 做得好的AI集成,核心功夫都花在"看不见的地方"——SAP侧的接口字段设计、服务权限细分、数据的预处理,AI侧的参数清洗、上下文轮次管理、缓存策略。这些基础工作做得越扎实,AI的表现就越显得"智能";反之,基础不牢靠,再强的模型也会频频出错。

最后再分享一个小技巧: 版本管理中,把SAP的OData服务定义文件和AI平台的Prompt配置放在同一个仓库里管理。 每次改动都走代码评审流程,这样任何一期修改导致的问题,都可以迅速追溯到是哪一方的变更引起的。我目前采用这个方式后,联调阶段的返工率至少降低了一半。

希望这份指南能帮到你。如果你在接入过程中遇到什么奇怪的问题,欢迎交流。


后记:文中所有代码和配置方案均基于SAP S/4HANA 2023版本和AI平台通用API接口实测,具体环境可能略有差异,请以实际系统为准。

更多推荐