最近看到一些SAP集成DeepSeek很好的方案,研究了下是怎样开发做到的,结果和大家分享下,由于DeepSeek不免费,百度文心一言要注册SSL证书,所以集成的是阿里的百炼大模型平台-通义千问,在云平台上注册获取密钥即可调用接口。本文包括问询平台,F1工具栏集成AI,GUI编辑器集成AI等实操。
演示效果:
一.问询平台
(效果图1)
1.创建输入文本框,设置参数调整文本框大小,在PBO中输出
2.创建输出文本框,设置参数调整文本框大小,在PBO中输出
3.在SCREEN中创建添加按钮,并在调用的方法中增加查询按钮调用接口方法,通过SET_TEXTSTREAM将接口返回内容写入输出文本框
下面为详细代码( 参数P_INPUT 和 P_INPUT 2用在下面F1帮助功能中):
Code listing for: ZCALL_AIDescription: 调用AI屏幕*&---------------------------------------------------------------------**& Report ZCALL_AI*&---------------------------------------------------------------------**&*&---------------------------------------------------------------------*REPORT ZCALL_AI.DATA: OK_CODE TYPE SY-UCOMM.DATA: LV_INPUT TYPE STRING,LV_OUTPUT TYPE STRING.PARAMETERS: P_INPUT TYPE STRING NO-DISPLAY,P_INPUT2 TYPE STRING NO-DISPLAY.CLASS LCL_HLP DEFINITION.PUBLIC SECTION.TYPES: BEGIN OF T_SOURCE,LINE TYPE CHAR255,END OF T_SOURCE.TYPES: TT_SOURCE TYPE STANDARD TABLE OF T_SOURCE WITH DEFAULT KEY.DATA:RESULTS TYPE STRING,SOURCE_EDITOR TYPE REF TO CL_GUI_TEXTEDIT,DEST_EDITOR TYPE REF TO CL_GUI_TEXTEDIT,ABAP_EDITOR TYPE REF TO CL_GUI_ABAPEDIT.METHODS: CREATE_SOURCE_EDITOR.METHODS: CREATE_DEST_EDITOR.METHODS: F_QUERY.METHODS: PAI IMPORTING VALUE(I_OKCODE) TYPE SY-UCOMM.ENDCLASS.START-OF-SELECTION.DATA(HLP) = NEW LCL_HLP( ).CALL SCREEN 0100.*&---------------------------------------------------------------------**& Module PBO OUTPUT*&---------------------------------------------------------------------**&*&---------------------------------------------------------------------*MODULE PBO OUTPUT.SET PF-STATUS 'STATUS_0100'.SET TITLEBAR 'TITLE'.HLP->CREATE_SOURCE_EDITOR( ).HLP->CREATE_DEST_EDITOR( ).ENDMODULE.*&---------------------------------------------------------------------**& Module PAI INPUT*&---------------------------------------------------------------------** text*----------------------------------------------------------------------*MODULE PAI INPUT.HLP->PAI( OK_CODE ).ENDMODULE.CLASS LCL_HLP IMPLEMENTATION.METHOD CREATE_SOURCE_EDITOR.IF SOURCE_EDITOR IS INITIAL.SOURCE_EDITOR = NEW #( PARENT = NEW CL_GUI_DOCKING_CONTAINER( SIDE = CL_GUI_DOCKING_CONTAINER=>DOCK_AT_TOPNO_AUTODEF_PROGID_DYNNR = ABAP_TRUEEXTENSION = 120 ) ) .ENDIF.*将输入信息返回倒界面上IF P_INPUT IS NOT INITIAL.CALL METHOD SOURCE_EDITOR->SET_TEXTSTREAMEXPORTINGTEXT = P_INPUTEXCEPTIONSOTHERS = 1.ENDIF.ENDMETHOD.METHOD CREATE_DEST_EDITOR.IF DEST_EDITOR IS INITIAL.DEST_EDITOR = NEW #( PARENT = NEW CL_GUI_DOCKING_CONTAINER( SIDE = CL_GUI_DOCKING_CONTAINER=>DOCK_AT_BOTTOMNO_AUTODEF_PROGID_DYNNR = ABAP_TRUEEXTENSION = 210 ) ) .ENDIF."隐藏输出文本框菜单栏CALL METHOD DEST_EDITOR->SET_TOOLBAR_MODEEXPORTINGTOOLBAR_MODE = 0EXCEPTIONSERROR_CNTL_CALL_METHOD = 1INVALID_PARAMETER = 2OTHERS = 3.IF SY-SUBRC <> 0.* Implement suitable error handling hereENDIF.*将输入信息返回倒界面上IF P_INPUT2 IS NOT INITIAL.CALL METHOD DEST_EDITOR->SET_TEXTSTREAMEXPORTINGTEXT = P_INPUT2EXCEPTIONSOTHERS = 1.ENDIF.ENDMETHOD.METHOD F_QUERY.DATA: SOURCE TYPE SOLI_TAB.SOURCE_EDITOR->GET_TEXT_AS_STREAM(IMPORTINGTEXT = SOURCEEXCEPTIONSERROR_CNTL_CALL_METHOD = 1OTHERS = 3).IF SY-SUBRC EQ 0.IF SOURCE IS INITIAL.MESSAGE S001(00) WITH '请输入查询信息' DISPLAY LIKE 'E' ##MG_MISSING ##NO_TEXT.RETURN.ENDIF.LV_INPUT = CL_BCS_CONVERT=>TXT_TO_STRING( IT_SOLI = SOURCE ).*调用阿里AI接口call function 'ZINT_AI_POST'EXPORTINGINPUT_STR = LV_INPUTIMPORTINGOUTPUT_STR = LV_OUTPUT.*将接口返回信息返回倒界面上CALL METHOD DEST_EDITOR->SET_TEXTSTREAMEXPORTINGTEXT = LV_OUTPUTEXCEPTIONSOTHERS = 1.ENDIF.ENDMETHOD.METHOD PAI.CLEAR SY-UCOMM.CASE I_OKCODE.WHEN 'BACK' .LEAVE TO SCREEN 0. "返回上一个屏幕WHEN 'CANCEL'.LEAVE TO SCREEN 0.WHEN 'EXIT'.LEAVE PROGRAM. "返回程序WHEN 'F_QUERY'.F_QUERY( ).ENDCASE.ENDMETHOD.ENDCLASS.*GUI Texts*----------------------------------------------------------* TITLE --> AI问询平台* TITLE --> AI问询平台*Messages*----------------------------------------------------------** Message class: 00*001 &1&2&3&4&5&6&7&8Extracted by Direct Download Enterprise version 1.3.1 - E.G.Mellodew. 1998-2005 UK. Sap Release 753
4.创建AI接口函数,
5.
接口中需要添加AI平台的授权密钥,和平时调用REST接口一样
LV_AUTH= 'sk-c8***********************'.
CALL METHOD LC_HTTP_CLIENT->REQUEST->SET_HEADER_FIELD
EXPORTING
NAME = 'Authorization'
VALUE = LV_AUTH.
以下为详细代码:
Code listing for function: ZINT_AI_POSTDescription: 阿里AI接口FUNCTION ZINT_AI_POST.*"----------------------------------------------------------------------*"*"本地接口:*" IMPORTING*" VALUE(INPUT_STR) TYPE STRING OPTIONAL*" VALUE(ABAP_FLG) TYPE CHAR1 OPTIONAL*" EXPORTING*" VALUE(OUTPUT_STR) TYPE STRING*" TABLES*" LT_OUTPUT STRUCTURE ZINT_AI_POST_OUT OPTIONAL*"----------------------------------------------------------------------* Global data declarationsDATA: LV_LEN TYPE I, "发送报文长度LV_URL TYPE STRING, "接口地址LC_HTTP_CLIENT TYPE REF TO IF_HTTP_CLIENT, "http客户端LV_AUTHORIZATION TYPE STRING,LV_CODE TYPE I, "HTTP 返回状态LV_REASON TYPE STRING. " HTTP 状态描述DATA: L_SYSUBRC TYPE I,L_ERROR_TEXT TYPE STRING.DATA: LV_TOKEN TYPE STRING.DATA: L_JSON_DATA TYPE STRING,L_MSG TYPE STRING,LV_AUTH TYPE STRING.DATA: I_REQUEST TYPE STRING,E_RESPONSE TYPE STRING.CLEAR: LV_URL,I_REQUEST."输入结构DATA: BEGIN OF LS_INPUT_MES,ROLE TYPE STRING,CONTENT TYPE STRING,END OF LS_INPUT_MES.DATA: BEGIN OF LS_INPUT,MODEL TYPE STRING,MESSAGES LIKE TABLE OF LS_INPUT_MES,END OF LS_INPUT.DATA: LS_REQ LIKE LS_INPUT_MES."输出结构DATA: BEGIN OF T_MESSAGE3,ROLE TYPE STRING,CONTENT TYPE STRING,END OF T_MESSAGE3.DATA: BEGIN OF T_CHOICES2,MESSAGE LIKE T_MESSAGE3,END OF T_CHOICES2.DATA: BEGIN OF LS_OUTPUT,CHOICES LIKE TABLE OF T_CHOICES2,END OF LS_OUTPUT.LS_INPUT-MODEL = 'qwen-plus'.LS_REQ-ROLE = 'user'.LS_REQ-CONTENT = INPUT_STR.APPEND LS_REQ TO LS_INPUT-MESSAGES.I_REQUEST = /UI2/CL_JSON=>SERIALIZE( DATA = LS_INPUTPRETTY_NAME = 'L' ).LV_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions'.*****创建http服务CALL METHOD CL_HTTP_CLIENT=>CREATE_BY_URLEXPORTINGURL = LV_URLIMPORTINGCLIENT = LC_HTTP_CLIENTEXCEPTIONSARGUMENT_NOT_FOUND = 1PLUGIN_NOT_ACTIVE = 2INTERNAL_ERROR = 3OTHERS = 4.IF SY-SUBRC <> 0.MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNOINTO L_MSGWITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.EXIT.ENDIF.CALL METHOD LC_HTTP_CLIENT->REQUEST->SET_HEADER_FIELDEXPORTINGNAME = 'Content-Type'VALUE = 'application/JSON; charset=utf-8'.LV_AUTH = 'sk-*********************************'.CALL METHOD LC_HTTP_CLIENT->REQUEST->SET_HEADER_FIELDEXPORTINGNAME = 'Authorization'VALUE = LV_AUTH.CALL METHOD LC_HTTP_CLIENT->REQUEST->SET_METHOD( 'POST' )."发送前数据准备LV_LEN = STRLEN( I_REQUEST ).CALL METHOD LC_HTTP_CLIENT->REQUEST->SET_CDATAEXPORTINGDATA = I_REQUESTOFFSET = 0LENGTH = LV_LEN.*****发送http服务CALL METHOD LC_HTTP_CLIENT->SENDEXCEPTIONSHTTP_COMMUNICATION_FAILURE = 1HTTP_INVALID_STATE = 2HTTP_PROCESSING_FAILED = 3HTTP_INVALID_TIMEOUT = 4OTHERS = 5.IF SY-SUBRC <> 0.MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNOINTO L_MSGWITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.EXIT.ENDIF.*****接收返回数据CALL METHOD LC_HTTP_CLIENT->RECEIVEEXCEPTIONSHTTP_COMMUNICATION_FAILURE = 1HTTP_INVALID_STATE = 2HTTP_PROCESSING_FAILED = 3OTHERS = 4.CLEAR E_RESPONSE.E_RESPONSE = LC_HTTP_CLIENT->RESPONSE->GET_CDATA( )."获取返回的状态信息CLEAR: LV_CODE, LV_REASON.CALL METHOD LC_HTTP_CLIENT->RESPONSE->GET_STATUSIMPORTINGCODE = LV_CODEREASON = LV_REASON./UI2/CL_JSON=>DESERIALIZE( EXPORTING JSON = E_RESPONSECHANGING DATA = LS_OUTPUT ).IF LV_CODE = '200'.SORT LS_OUTPUT-CHOICES[].READ TABLE LS_OUTPUT-CHOICES[] INDEX 1 INTO DATA(LS_OUT) .IF SY-SUBRC = 0.OUTPUT_STR = LS_OUT-MESSAGE-CONTENT.ENDIF.ELSE.OUTPUT_STR = '调用失败!'.ENDIF.IF ABAP_FLG = 'Y'.DATA: ES_OUTPUT LIKE ZINT_AI_POST_OUT.DATA: LT_TABLE TYPE TABLE OF STRING.DATA: LV_ROW_NUMBER TYPE I,LV_ROW_NUMBER_BEGIN TYPE I,LV_ROW_NUMBER_END TYPE I.SPLIT OUTPUT_STR AT CL_ABAP_CHAR_UTILITIES=>NEWLINE INTO TABLE LT_TABLE.LV_ROW_NUMBER_BEGIN = 0.LV_ROW_NUMBER_END = 0.LOOP AT LT_TABLE INTO DATA(LS_TABLE).LV_ROW_NUMBER = SY-TABIX.IF LS_TABLE CS 'report' OR LS_TABLE CS 'REPORT'.LV_ROW_NUMBER_BEGIN = LV_ROW_NUMBER.EXIT.ENDIF.ENDLOOP.LV_ROW_NUMBER_BEGIN = LV_ROW_NUMBER_BEGIN + 1.LOOP AT LT_TABLE INTO LS_TABLE FROM LV_ROW_NUMBER_BEGIN.ES_OUTPUT-TEXT = LS_TABLE.APPEND ES_OUTPUT TO LT_OUTPUT.ENDLOOP.ENDIF."关闭接口CALL METHOD LC_HTTP_CLIENT->CLOSE.ENDFUNCTION.*Messages*----------------------------------------------------------** Message class: Hard coded* 获取token失败Extracted by Direct Download Enterprise version 1.3 - E.G.Mellodew. 1998-2004 UK. Sap Release 753
二.集成F1帮助工具栏
当用户遇到系统报错,经常会拿报错信息(包括对消息类,消息号和消息内容)在网上搜索原因和解决方案,那将AI集成到F1工具栏实现一键查询,是个不错的选择。
(效果图1)
(效果图2)
1.以下是添加F1工具栏按钮方式
1.1通过SM30维护表EPSS_TBC1,维护按钮。

其中按钮图标名称是内码,可以通过执行程序: SHOWICON,查看各图标对应的值,比如&15&为执行对象按钮。
1.2工具栏按钮文本维护,通过SM30维护表EPSS_TBC1T,
维护ZH同时DE语言也必须维护否则报错。
1.3处理按钮方法维护,参考CL_EPSS_CUSTOMIZING_SERVICE复制 ZCL_EPSS_AI_SERVICE
1.4SE24复制类CL_EPSS_CUSTOMIZING_SERVICE到ZCL_EPSS_AI_SERVICE
在SET_BUTTON_STATE方法中添加按钮方法
在HANDLE_EVENT方法中调用接口,这里需要获取F1弹框中的消息号等内容,用来作为AI查询问题的内容,对消息内容处理后拼接为AI可以读懂的语言。调用接口后将输入信息和返回信息写入问询平台展示,代码样例如下图。
三.集成SE38编辑器
在报表中输入需求,通过右键AI生成报表,自动生成的代码可供参考,现阶段对于报表模板和简单的报表有些帮助,质量取决于AI平台能力。
查询内容为鼠标选中的内容,可以多行,第一列的*可有可无。
编辑器集成AI平台开发过程主要分为2步。
(效果图1)
(效果图2)
1.编辑器按钮添加,开发思路是DEBUG,看都走过哪些方法和类,是否有增强点,在类CL_CTXMNU_MGR的方法CREATE_PROXY中发现可以做隐式增强,添加山下文菜单,限制SE38显示,定义方法名称ZAI1,ZAI2(CODE为4位,如果超长后面实施方法时读取不到)
2.实施按钮方法的过程没有找到增强点,所以通过修改源码的方式找到合适的点。
思路是在第一步完成后,如果ZGPT方法未实施,会报下图错误,F1点击消息来源查看报错位置,定位到报错位置是函数:USERCOM_INPUT,其他按钮比如右键注释等更改屏幕内容操作也会走该函数,所以在这个位置添加按钮逻辑。


开发代码逻辑,其中需要注意两点,第一点发现编辑器的内容是以内表方式存在CONTENT[]和CONTECT_C[]中,需要在接口中将STRING类型的AI接口返回信息根据换行转换为内表存储方式,然后再LOOP写入CONTENT中。第二点需要调用
CALLFUNCTION 'EXECUTE_FUNCTION'
EXPORTING
c_editor = c_editor
fcode_i = 'SETT'
TABLES
content = content.
该方法会将后台文本更新到SE38编辑器中显示。
当然这里还添加了一些校验只有可编辑转台可以点代码生成(通过edit-app_disp = 'A'.来判断,DEBUG发现)。
此外还有获取鼠标选中的行文本起始行和结尾行,为读取CONTENT[]拼接后作为AI接口输入请求。可以通过ZINT_AI_POST_OUT->get_selection_pos来获取鼠标选中起始行与结尾行。
以下为详细代码插入处*{ INSERT DEVK905163
代码逻辑可能有一些不足和需要优化的地方,欢迎一起交流。

