本文档简要介绍了如何在 SAP BTP、ABAP 环境中使用 Vertex AI SDK for ABAP 通过 Gemini 进行 SAP 函数调用。
您可以定义自定义函数,并使用函数调用功能将其提供给 Gemini 模型。模型不会直接调用自定义函数,而是生成指定函数名称和建议参数的结构化数据输出。借助此输出,您可以编写采用结构化输出并调用外部 API 的应用。然后,可以将生成的 API 输出并入进一步的模型提示中,以便获得更全面的查询回答。
Vertex AI SDK for ABAP 通过以下方式让 ABAP 开发者有机会调用在 SAP 函数模块中编写的自定义逻辑,从而简化他们的函数调用操作:
- 将 SAP 函数模块名称或 OData(开放式数据协议)服务名称作为函数声明传递给模型,描述函数或服务的名称、用途和相关参数。
- 在调用模型时,隐式设置 SAP 函数模块或 OData 服务的自动调用。
准备工作
在通过 Vertex AI SDK for ABAP 使用 Gemini 进行 SAP 函数调用之前,请确保您或您的管理员已满足以下前提条件:
- 在 Google Cloud 项目中启用了 Vertex AI API。
- 在 SAP 环境中安装了 Vertex AI SDK for ABAP。
- 设置身份验证以访问 Vertex AI API。
- 配置了模型生成参数。
通过调用 SAP 函数模块,使用 SAP 数据丰富 Gemini AI 模型上下文
本部分介绍了如何通过调用 SAP 函数模块使用 SAP 数据来丰富 Gemini AI 模型上下文。
以下是 ABAP 开发者调用 SAP 函数模块的典型流程:
- 用户提供输入提示。
- SDK 将输入提示和函数声明传递给模型。
- 该模型会检查提示和声明的函数,以推导要调用的函数,并建议用于调用该函数的参数值。
- 如果设置了自动调用,SDK 会调用 SAP 函数模块。
- 然后,SDK 会使用所调用函数的输出调用模型。
- 模型会以可靠的答案回答使用所调用函数的输出丰富的最终提示。
- SDK 会将回答返回给用户。
如果您选择不自动调用 SAP 函数模块,则 SDK 可让您在不调用任何 SAP 函数模块的情况下使用函数调用功能。在这种情况下,您可以遵循典型的函数调用工作流程来使用外部工具,例如 API 和函数。
实例化多模态 Gemini 调用程序类
如需在 SAP 中调用函数调用,请使用 /GOOG/CL_GENERATIVE_MODEL
类。您可以通过传递在模型生成参数中配置的模型键来实例化该类。
DATA(lo_model) = NEW /goog/cl_generative_model( iv_model_key = 'MODEL_KEY' ).
将 MODEL_KEY
替换为模型键名,该名称在模型生成参数中进行配置。
创建 SAP 函数模块
如需创建可由 SDK 自动调用的 SAP 函数模块,请遵循提供的架构:
类别 | 参数名称 | 关联类型 |
---|---|---|
导入 | IT_FUNCTION_PARAMETERS |
/GOOG/T_FUNCTION_PARAMETERS |
导出 | EV_FUNCTION_RESPONSE |
STRING |
更改 | CV_PROMPT |
STRING |
异常 | /GOOG/CX_SDK |
Exception Class |
根据导入参数,在函数模块中编写您的自定义逻辑,该逻辑可以是通过 SELECT
查询提取 SAP 数据,也可以是调用外部 API 或模块以获取缺失的信息。
使用要反馈给 LLM 上下文的信息设置导出参数 EV_FUNCTION_RESPONSE
。您还可以根据自定义逻辑和业务要求更改或修改 CV_PROMPT
中的提示文本,以便根据不同的业务场景进一步指示 LLM。
添加函数声明
如需向 LLM 上下文添加函数声明,您可以使用 ADD_FUNCTION_DECLARATION
方法。每当您需要向上下文添加函数时,都应调用 ADD_FUNCTION_DECLARATION
方法。
DATA lt_parameters TYPE /goog/cl_generative_model=>tt_parameter_properties.
APPEND VALUE #( parameter_name = 'PARAMETER_NAME'
type = 'PARAMETER_TYPE'
description = 'PARAMETER_DESCRIPTION'
is_required = 'PARAMETER_IS_REQUIRED' ) TO lt_parameters.
lo_model->add_function_declaration( iv_name = 'FUNCTION_MODULE_NAME'
iv_description = 'FUNCTION_MODULE_DESCRIPTION'
it_parameters = lt_parameters ).
替换以下内容:
PARAMETER_NAME
:参数的名称。PARAMETER_TYPE
:参数的数据类型,例如string
、integer
或boolean
。PARAMETER_DESCRIPTION
:清楚地说明参数的用途和预期格式。PARAMETER_IS_REQUIRED
:如果此参数是函数运行所必需的,请将其值设置为ABAP_TRUE
。FUNCTION_MODULE_NAME
:SAP 函数模块的名称。FUNCTION_MODULE_DESCRIPTION
:SAP 函数模块的说明。
您还可以声明不带参数的函数,该函数可用作回退或备用函数。如果用户提示未提供足够的信息来调用特定函数,您可以指示 Gemini 选择此回退函数。
设置 SAP 函数模块的自动调用
如需设置模型选择的所选 SAP 函数的自动调用,您可以使用 SET_AUTO_INVOKE_SAP_FUNCTION
方法。如果在导入参数 IV_AUTO_INVOKE
中传递 ABAP_TRUE
,则 SDK 会调用函数模块,并且其回答会包含在 LLM 上下文中,以生成最终回答。
您必须按照创建 SAP 函数模块部分中所述的架构定义函数模块。
lo_model->set_auto_invoke_sap_function( abap_true ).
使用函数调用生成内容
如需将提示文本传递给 Gemini 模型,您可以使用 GENERATE_CONTENT
方法。如需获取 Gemini 生成的回答以及通过函数调用从 SAP 函数模块添加的额外上下文,请使用 GET_TEXT
方法。
DATA(lv_response) = lo_model->generate_content( iv_prompt_text ='PROMPT'
)->get_text( ).
将 PROMPT
替换为您的文本提示。
获取所选函数名称和参数值
如需获取 Gemini 选择的函数(从声明的函数中选择)及其建议的参数,请使用 GET_FUNCTION_CALL
方法。
DATA(lo_response) = lo_model_key->set_auto_invoke_sap_function( abap_true
)->generate_content( iv_prompt_text = 'PROMPT' ).
lo_response->get_function_call( IMPORTING ev_function_name = DATA(lv_function_name)
et_function_parameters = DATA(lt_function_parameters) ).
将 PROMPT
替换为您的文本提示。
您可以从 LV_FUNCTION_NAME
获取 Gemini 所选函数的名称,并从 LT_FUNCTION_PARAMETERS
获取建议的参数。您可以根据贵企业的安全信息和事件管理指南,使用这些信息验证、跟踪和记录 Gemini 操作。
代码示例
以下代码示例展示了如何使用 SAP 函数调用来接收模型的最终回答。
DATA lt_parameters TYPE /goog/cl_generative_model=>tt_parameter_properties.
TRY.
DATA(lo_model) = NEW /goog/cl_generative_model( iv_model_key = 'MODEL_KEY' ).
APPEND VALUE #( parameter_name = 'PARAMETER_NAME'
type = 'PARAMETER_TYPE'
description = 'PARAMETER_DESCRIPTION'
is_required = 'PARAMETER_IS_REQUIRED' ) TO lt_parameters.
DATA(lv_response) = lo_model->add_function_declaration(
iv_name = 'FUNCTION_MODULE_NAME'
iv_description = 'FUNCTION_MODULE_DESCRIPTION'
it_parameters = lt_parameters
)->set_auto_invoke_sap_function( abap_true
)->generate_content( iv_prompt_text ='PROMPT'
)->get_text( ).
IF lv_response IS NOT INITIAL.
cl_demo_output=>display( lv_response ).
ENDIF.
CATCH /goog/cx_sdk INTO DATA(lo_cx_sdk).
cl_demo_output=>display( lo_cx_sdk->get_text( ) ).
ENDTRY.
替换以下内容:
MODEL_KEY
:模型键名,可在模型生成参数中配置。PARAMETER_NAME
:参数的名称。PARAMETER_TYPE
:参数的数据类型,例如string
、integer
或boolean
。PARAMETER_DESCRIPTION
:清楚地说明参数的用途和预期格式。PARAMETER_IS_REQUIRED
:如果此参数是函数运行所必需的,请将其值设置为ABAP_TRUE
。FUNCTION_MODULE_NAME
:SAP 函数模块的名称。FUNCTION_MODULE_DESCRIPTION
:SAP 函数模块的说明。PROMPT
:您的文本提示。
通过调用 OData 服务,使用 SAP 数据丰富 Gemini AI 模型上下文
本部分介绍了如何通过调用 OData 服务使用 SAP 数据来丰富 Gemini AI 模型上下文。
以下是 ABAP 开发者调用 OData 服务的典型流程:
- 用户提供输入提示。
- SDK 将输入提示和函数声明传递给模型。
- 该模型会检查提示和声明的函数,以推导要调用的函数,并建议用于调用该函数的参数值。
- 如果设置了自动调用,SDK 会调用 OData 服务。
- 然后,SDK 会使用所调用 OData 服务的输出调用模型。
- 模型会以可靠的答案回答使用所调用 OData 服务的输出丰富的最终提示。
- SDK 会将回答返回给用户。
如果您选择不自动调用 OData 服务,则 SDK 可让您在不调用任何 OData 服务的情况下使用函数调用功能。在这种情况下,您可以遵循典型的函数调用工作流程来使用外部工具,例如 API 和函数。
创建 OData 服务
如需创建可由 SDK 作为函数自动调用的 OData 服务,请使用以下架构:
{
"UserRequest": "Input Prompt as user request",
"FunctionResponse": null,
"ModifiedUserRequest": null,
"ContextParameters": [
{
"ParameterName": "Parameter 1",
"ParameterValue": "Value 1"
},
{
"ParameterName": "Parameter 2",
"ParameterValue": "Value 2"
}
]
}
下表提供了此架构中使用的字段的相关信息:
架构字段 | 字段类型 | 输入/输出模式 | 说明 |
---|---|---|---|
UserRequest |
String |
仅限输入 | 用户输入的输入提示。 |
FunctionResponse |
String |
仅限输出 | OData 服务的输出。它可以是单个值,也可以是序列化的 JSON 字符串。 |
ModifiedUserRequest |
String |
仅限输出 | 经过修改的 UserRequest ,将作为提示馈送给 Gemini。 |
ContextParameters |
Table of parameters |
仅限输入 | 参数表,其中包含参数名称和值。 |
ParameterName |
String |
仅限输入 | 函数参数的名称。 |
ParameterValue |
String |
仅限输入 | Gemini 建议的函数参数值。 |
创建 OData 服务实体
使用上述架构创建实体。
此实体会将用户请求作为提示接受,将其转发给 Gemini,并使用 Vertex AI SDK for ABAP 声明为函数。此实体还会将 OData 函数响应从后端 SAP 系统传回到 BTP,然后将其添加到 Gemini AI 模型上下文中。
- 为新项设置合适的名称。
为以下属性设置值。保留所有其他属性的默认值。
名称 是关键吗? EDM 核心类型 ABAP 字段名称 UserRequest
是 Edm.String
USER_REQUEST FunctionResponse
否 Edm.String
FUNCTION_RESPONSE ModifiedUserRequest
否 Edm.String
MODIFIED_USER_REQUEST
如果您想在同一 OData 服务中放置更多实体,请使用相同的架构创建这些实体。
创建另一个名为
ContextParameters
的实体,并为其指定以下属性。保留所有其他属性的默认值。此实体包含 Gemini 模型提供的函数参数及其值。
名称 是关键吗? EDM 核心类型 ABAP 字段名称 ParameterName
是 Edm.String
PARAMETER_NAME ParameterValue
是 Edm.String
PARAMETER_VALUE 为您在前面的步骤中创建的所有实体创建 entity 集。
将您在第 1 步中创建的每个实体与您在第 2 步中创建的
ContextParameters
实体相关联,如下所示:- 为关联设置名称。
- 在 Principal Entity(主要实体)字段中,设置您在第 1 步中创建的实体的名称。
- 在主要实体基数字段中,设置
M
。 - 在依赖项字段中,设置
ContextParameters
。 - 在依赖实体基数字段中,设置
M
。 - 保存并生成 OData 运行时工件。
在 SAP Gateway 中添加创建的 OData 服务,并激活 ICF 节点。
为 OData 元数据生成 EDMX 文件,如下所示:
- 前往 TCode /iwfnd/maint_services,获取 OData 服务的元数据。
- 设置格式并以
.edmx
文件扩展名保存生成的 XML。
编写 OData 函数逻辑
在生成的
MPC_EXT
类中,添加并启用深度实体类型:TYPES: BEGIN OF ts_function_deep_entity, user_request TYPE string, function_response TYPE string, modified_user_request TYPE string, context_parameters TYPE TABLE OF ts_contextparameters WITH DEFAULT KEY, END OF ts_function_deep_entity.
请完成以下步骤,重新定义生成的
DPC_EXT
类的CREATE_DEEP_ENTITY
方法:- 如果您在创建 OData 服务实体部分创建了多个 OData 实体,请为每个 OData 实体添加一个
CASE
语句。 - 将 ABAP 逻辑写入响应的
get
或prepare
,以在 BTP 应用中为 Gemini 增强上下文。 - 在 FUNCTION_RESPONSE 字段中,设置响应。
- 在 MODIFIED_USER_REQUEST 字段中,设置修改后的提示。
- 使用
COPY_DATA_TO_REF
OData 方法,在消息中绑定整个响应。
以下代码段是 ABAP 逻辑示例:
TRY. DATA: ls_request TYPE <z*_mpc_ext>=>ts_function_deep_entity. CASE io_tech_request_context->get_entity_type_name( ). WHEN <z*_mpc_ext>=>gc_ENTITY_NAME. CALL METHOD io_data_provider->read_entry_data IMPORTING es_data = ls_request. <ABAP logic to formulate OData function response> ls_request-modified_user_request = 'MODIFIED_GEMINI_PROMPT'. ls_request-function_response = 'ODATA_FUNCTION_RESPONSE'. CALL METHOD me->copy_data_to_ref EXPORTING is_data = ls_request CHANGING cr_data = er_deep_entity. ENDCASE. CATCH /iwbep/cx_mgw_busi_exception. CATCH /iwbep/cx_mgw_tech_exception. ENDTRY. ```
- 如果您在创建 OData 服务实体部分创建了多个 OData 实体,请为每个 OData 实体添加一个
替换以下内容:
ENTITY_TYPE
:您在创建 OData 服务实体部分的第 1 步中创建的 OData 实体的名称MODIFIED_GEMINI_PROMPT
:Gemini 提供的修改版提示ODATA_FUNCTION_RESPONSE
:OData 服务提供的响应
如果您有多个字段,或者有要作为函数响应传递的嵌套结构或表,则可以使用 SDK 的 /GOOG/CL_JSON_UTIL
类的 SERIALIZE_JSON
方法将 ABAP 类型序列化为字符串。
在 SAP BTP 上将 OData 服务定义为服务使用模型
创建 OData 服务后,您需要在 SAP BTP 环境中将其定义为服务使用模型。为此,您需要创建服务使用模型、HTTP 出站服务、通信场景和通信安排。
创建服务使用模型
- 在 ABAP 项目中,打开上下文菜单,然后依次选择新建 > 其他 ABAP 代码库对象 > 企业服务 > 服务使用模型。
- 在新服务使用模式窗口中,完成以下步骤:
- 在 Package 字段中,选择并上传您在上一部分中生成的 EDMX 文件。
- 输入名称和说明。
- 在远程使用模式字段中,选择 OData。
- 点击完成。
创建 HTTP 出站服务
- 在 ABAP 项目中,打开上下文菜单。
- 选择您的软件包,然后依次点击新建 > 其他 ABAP 代码库对象。
- 在服务类型字段中,选择 HTTP 服务。
在 Default Path Prefix(默认路径前缀)字段中,输入后端 SAP 系统中 OData 服务的路径前缀。
您可以访问 SAP Gateway 客户端来查找 OData 路径前缀。您在请求 URI 字段中看到的值是 OData 服务的路径前缀。
点击下一步。
创建通信场景
创建 HTTP 出站服务后,您必须创建通信场景并将出站服务分配给该场景。为此,请完成以下步骤:
- 在 ABAP 项目中,选择通信场景,然后点击下一步。
- 在 New Communication Scenario 窗口中,完成以下步骤:
- 输入名称和说明。
- 点击下一步。
- 在 Communication Scenario Type 字段中,选择 Customer Managed。
- 前往出站标签页。
- 在 Allowed Instances 字段中,选择 Per scenario & communication system one instance。
- 在支持的身份验证方法字段中,选中以下复选框:基本、X.509 和 OAuth 2.0。
- 在 OAuth 2.0 Grant Type(OAuth 2.0 授权类型)字段中,选择 SAML 2.0 Bearer Assertion(SAML 2.0 Bearer Assertion)。
- 在出站服务部分下,点击添加,然后选择您在上一部分创建的出站服务。
- 在 Outbound Service 部分,确保 Default Path Prefix(默认路径前缀)正确无误。如果未同步,请点击同步。
- 保存通信场景。
创建通信安排
- 访问安装了 ABAP SDK for Google Cloud 的 BTP ABAP 系统的 SAP Fiori launchpad。
打开 Communication Arrangement 应用。
- 点击 New(新建)。
在显示的 New Communication Arrangement 对话框中,输入以下字段的值:
- 场景:选择您在创建通信场景部分中创建的通信场景。
- Arrangement name:输入通信安排的名称。
点击创建。
对于显示的通信安排,请在 Communication System 字段中,选择您在上一步中创建的通信系统。
点击保存。
实例化多模态 Gemini 调用程序类
如需在 SAP 中调用函数调用,请使用 /GOOG/CL_GENERATIVE_MODEL
类。您可以通过传递在模型生成参数中配置的模型键来实例化该类。
DATA(lo_model) = NEW /goog/cl_generative_model( iv_model_key = 'MODEL_KEY' ).
将 MODEL_KEY
替换为模型键名称,该名称在模型生成参数中进行配置。
添加函数声明
如需将 OData 服务作为函数声明添加到 LLM 上下文,您可以使用 ADD_FUNCTION_DECLARATION
方法。每当您需要将 OData 服务作为函数添加到上下文时,都应调用 ADD_FUNCTION_DECLARATION
方法。
DATA lt_parameters TYPE /goog/cl_generative_model=>tt_parameter_properties.
DATA ls_connection_parameters TYPE /goog/cl_generative_model=>ty_connection_parameters.
APPEND VALUE #( parameter_name = 'PARAMETER_NAME'
type = 'PARAMETER_TYPE'
description = 'PARAMETER_DESCRIPTION'
is_required = 'PARAMETER_IS_REQUIRED' ) TO lt_parameters.
ls_connection_parameters-connection_type = 'ODATA'.
ls_connection_parameters-comm_scenario = 'COMMUNICATION_SCENARIO'.
ls_connection_parameters-service_id = 'ODATA_SERVICE_ID'.
ls_connection_parameters-proxy_model_id = 'ODATA_SERVICE_CONSUMPTION_MODEL_ID'.
ls_connection_parameters-relative_service_root = 'ODATA_ROOT_URI'.
ls_connection_parameters-entity_set_name = 'ODATA_ENTITY_SET_NAME'.
lo_model->add_function_declaration( iv_name = 'FUNCTION_NAME'
iv_description = 'FUNCTION_DESCRIPTION'
it_parameters = lt_parameters
is_connection_parameters = ls_connection_parameters ).
替换以下内容:
PARAMETER_NAME
:参数的名称PARAMETER_TYPE
:参数的数据类型,例如string
、integer
或boolean
PARAMETER_DESCRIPTION
:清楚地说明参数的用途和预期格式PARAMETER_IS_REQUIRED
:如果此参数是函数运行所必需的,请将其值设置为ABAP_TRUE
COMMUNICATION_SCENARIO
:您创建的通信场景的 IDODATA_SERVICE_ID
:您为 OData 服务创建的出站服务的 IDODATA_SERVICE_CONSUMPTION_MODEL_ID
:您为 OData 服务创建的服务使用模型的 IDODATA_ROOT_URI
:后端 SAP 系统中 OData 服务的根 URIODATA_ENTITY_SET_NAME
:要声明为函数的 OData 服务的实体集名称FUNCTION_NAME
:您为要使用的 OData 服务声明的函数的名称FUNCTION_DESCRIPTION
:您为要使用的 OData 服务声明的函数的说明
设置 OData 服务的自动调用
如需设置 Gemini 模型选择的 SAP 函数 OData 服务的自动调用,您可以使用 SET_AUTO_INVOKE_SAP_FUNCTION
方法。如果在导入参数 IV_AUTO_INVOKE
中传递 ABAP_TRUE
,则 SDK 会调用函数模块,并且其回答会包含在 LLM 上下文中,以生成最终回答。
您必须按照创建 SAP 函数模块部分中所述的架构定义函数模块。
lo_model->set_auto_invoke_sap_function( abap_true ).
使用函数调用生成内容
如需将提示文本传递给 Gemini 模型,您可以使用 GENERATE_CONTENT
方法。如需获取 Gemini 生成的回答以及通过函数调用从 SAP 函数模块添加的额外上下文,请使用 GET_TEXT
方法。
DATA(lv_response) = lo_model->generate_content( iv_prompt_text ='PROMPT'
)->get_text( ).
将 PROMPT
替换为您的文本提示。
获取所选函数名称和参数值
如需获取 Gemini 选择的函数(从声明的函数中选择)及其建议的参数,请使用 GET_FUNCTION_CALL
方法。
DATA(lo_response) = lo_model_key->set_auto_invoke_sap_function( abap_true
)->generate_content( iv_prompt_text = 'PROMPT' ).
lo_response->get_function_call( IMPORTING ev_function_name = DATA(lv_function_name)
et_function_parameters = DATA(lt_function_parameters) ).
代码示例
以下代码示例展示了如何将 SAP 函数调用与 Odata 服务搭配使用,以接收模型的最终回答:
DATA lt_parameters TYPE /goog/cl_generative_model=>tt_parameter_properties.
DATA ls_connection_parameters TYPE /goog/cl_generative_model=>ty_connection_parameters.
TRY.
DATA(lo_model) = NEW /goog/cl_generative_model( iv_model_key = 'MODEL_KEY' ).
APPEND VALUE #( parameter_name = 'PARAMETER_NAME'
type = 'PARAMETER_TYPE'
description = 'PARAMETER_DESCRIPTION'
is_required = 'PARAMETER_IS_REQUIRED' ) TO lt_parameters.
ls_connection_parameters-connection_type = 'ODATA'.
ls_connection_parameters-comm_scenario = 'COMMUNICATION_SCENARIO'.
ls_connection_parameters-service_id = 'ODATA_SERVICE_ID'.
ls_connection_parameters-proxy_model_id = 'ODATA_SERVICE_CONSUMPTION_MODEL_ID'.
ls_connection_parameters-relative_service_root = 'ODATA_ROOT_URI'.
ls_connection_parameters-entity_set_name = 'ODATA_ENTITY_SET_NAME'.
DATA(lv_response) = lo_model_key->add_function_declaration(
iv_name = 'FUNCTION_NAME'
iv_description = 'FUNCTION_DESCRIPTION'
it_parameters = lt_parameters
is_connection_parameters = ls_connection_parameters
)->set_auto_invoke_sap_function( abap_true
)->generate_content( iv_prompt_text ='PROMPT'
)->get_text( ).
IF lv_response IS NOT INITIAL.
out->write( lv_response ).
ENDIF.
CATCH /goog/cx_sdk INTO DATA(lo_cx_sdk).
out->write( lo_cx_sdk->get_text( ) ).
ENDTRY.
后续步骤
- 了解使用 SAP BTP 版本的 ABAP SDK for Google Cloud 进行应用开发。
- 在 Cloud 论坛上提出问题并与社区讨论 Vertex AI SDK for ABAP。