搭配使用 SAP 函式呼叫與 Vertex AI 託管模型

本文說明如何使用 Vertex AI SDK for ABAP,搭配下列 Vertex AI 代管模型使用 SAP 函式呼叫:

您可以使用函式呼叫功能定義自訂函式,並提供給 Gemini 和 Claude 模型。模型不會直接叫用自訂函式,而是產生結構化資料輸出內容,指定函式名稱和建議的引數。您可以根據這項輸出內容編寫應用程式,擷取結構化輸出內容並呼叫外部 API。然後將產生的 API 輸出內容納入進一步的模型提示, 以便提供更全面的查詢回應。

ABAP 適用的 Vertex AI SDK 可讓 ABAP 開發人員呼叫函式,方法是提供機會,讓他們透過下列方式叫用 SAP 函式模組中編寫的自訂邏輯:

  • SAP 函式模組名稱做為函式宣告傳遞至模型,並說明函式名稱、用途和相關參數。
  • 在叫用模型時,隱含設定 SAP 函式模組的自動叫用。

以下是 ABAP 開發人員呼叫 SAP 函式的典型歷程:

  1. 使用者提供輸入提示。
  2. SDK 會將輸入提示和函式宣告傳遞至模型。
  3. 模型會檢查提示和已宣告的函式,推導出要呼叫的函式,並建議呼叫函式的參數值。
  4. 如果設定自動叫用,SDK 會呼叫 SAP 函式模組。
  5. 接著,SDK 會使用所呼叫函式的輸出內容叫用模型。
  6. 模型會根據最終提示 (已加入所呼叫函式的輸出內容),提供可靠的答案
  7. SDK 會將回應傳回給使用者。

使用 Gemini 呼叫 SAP 函式

如果您選擇不自動叫用 SAP 函式模組,SDK 可讓您使用函式呼叫功能,而不必叫用任何 SAP 函式模組。在這種情況下,您可以按照一般的函式呼叫工作流程,使用 API 和函式等外部工具。

事前準備

使用 Vertex AI SDK for ABAP 搭配 Gemini 呼叫 SAP 函式前,請確認您或管理員已完成下列必要條件:

Gemini:

Claude:

使用 SAP 資料擴充 AI 模型內容

本節說明如何使用 Vertex AI SDK for ABAP,透過 SAP 資料擴充 AI 模型背景資訊。

將多模態呼叫器類別例項化

如要在 SAP 中使用 Gemini 模型叫用函式呼叫,請使用 /GOOG/CL_GENERATIVE_MODEL 類別。

如要在 SAP 中使用 Claude 模型叫用函式呼叫,請使用 /GOOG/CL_MODEL_CLAUDE 類別。

您需要傳遞在模型生成參數中設定的模型金鑰,才能例項化類別。

Gemini

DATA(lo_model) = NEW /goog/cl_generative_model( iv_model_key = 'MODEL_KEY' ).

Claude

DATA(lo_model) = NEW /goog/cl_model_claude( 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

根據匯入參數,在函式模組中編寫自訂邏輯,透過查詢擷取 SAP 資料,或呼叫外部 API 或模組來取得缺少的資訊。SELECT

使用要回饋給 LLM 情境的資訊,設定匯出參數 EV_FUNCTION_RESPONSE。您也可以根據自訂邏輯和業務需求,在 CV_PROMPT 中變更或修改提示文字,進一步根據不同業務情境指示 LLM。

新增函式宣告

如要將函式宣告新增至 LLM 環境,可以使用 ADD_FUNCTION_DECLARATION 方法。每次需要將函式新增至內容時,請呼叫 ADD_FUNCTION_DECLARATION 方法。

Gemini

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 ).

Claude

DATA lt_parameters TYPE /goog/cl_model_claude=>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:參數的資料型別,例如 stringintegerboolean
  • PARAMETER_DESCRIPTION:清楚說明參數用途和預期格式。
  • PARAMETER_IS_REQUIRED:如果函式運作時必須使用這個參數,請將值設為 ABAP_TRUE
  • FUNCTION_MODULE_NAME:SAP 函式模組的名稱。
  • FUNCTION_MODULE_DESCRIPTION:SAP 函式模組的說明。

您也可以宣告不含參數的函式,做為備用函式。如果使用者提示提供的資訊不足,無法呼叫特定函式,您可以指示模型選取這個備援函式。

設定自動叫用 SAP 函式模組

如要設定自動叫用模型選取的 SAP 函式,可以使用 SET_AUTO_INVOKE_SAP_FUNCTION 方法。如果 ABAP_TRUE 是在匯入參數 IV_AUTO_INVOKE 中傳遞,SDK 就會叫用函式模組,並將其回應納入 LLM 環境,以生成最終回應。

您必須按照「建立 SAP 函式模組」一節所述的結構定義,定義函式模組。

lo_model->set_auto_invoke_sap_function( abap_true ).

使用函式呼叫生成內容

如要將提示文字傳遞至模型,可以使用 GENERATE_CONTENT 方法。 如要取得模型生成的回應,並透過函式呼叫從 SAP 函式模組新增額外背景資訊,請使用 GET_TEXT 方法。

DATA(lv_response) = lo_model->generate_content( iv_prompt_text ='PROMPT'
                           )->get_text( ).

PROMPT 替換為您的文字提示

取得所選函式名稱和參數值

如要取得模型選取的函式 (從已宣告的函式中選取) 及其建議的參數,請使用 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 取得所選函式的名稱,並從 LT_FUNCTION_PARAMETERS 取得建議的參數。您可以根據企業安全資訊和事件管理指南,使用這項資訊驗證、追蹤及記錄模型動作。

程式碼範例

以下程式碼範例說明如何使用 SAP 函式呼叫,從模型接收最終回應。

Gemini

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.

Claude

DATA lt_parameters TYPE /goog/cl_model_claude=>tt_parameter_properties.
TRY.
DATA(lo_model) = NEW /goog/cl_model_claude( 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:參數的資料型別,例如 stringintegerboolean
  • PARAMETER_DESCRIPTION:清楚說明參數用途和預期格式。
  • PARAMETER_IS_REQUIRED:如果函式運作時必須使用這個參數,請將值設為 ABAP_TRUE
  • FUNCTION_MODULE_NAME:SAP 函式模組的名稱。
  • FUNCTION_MODULE_DESCRIPTION:SAP 函式模組的說明。
  • PROMPT:您的文字提示

自動函式鏈結

自動函式鏈結功能可讓您叫用多個使用者定義的函式模組,產生回覆。只有在啟用 SAP 函式模組的自動叫用功能時,系統才會支援這項功能。

下列程式碼範例說明自動函式鏈結。對於提示 Get the air quality in my current location,模型會先叫用函式模組 Z_GET_CURRENT_LOCATION 取得經緯度資訊,然後將經緯度資訊傳遞至函式模組 Z_GET_CURRENT_AIR_QUALITY,取得指定經緯度點的空氣品質。

Gemini

gv_prompt = 'Get the air quality in my current location'.
gv_system_instruction = 'You are a helpful weather assistant bot. You can turn find my location and get the weather information like temperature' &&
'You can also alert me about EarthQuakes and Storm.' &&
'You can also provide me information on Air Quality based on a location' &&
'Do not perform any other tasks.'.
TRY.
    DATA(lo_model_key) = NEW /goog/cl_generative_model( iv_model_key = 'gemini-flash-2' ).
    gv_final_op = lo_model_key->gs_ai_config-model_id.
    lo_model_key->add_function_declaration( iv_name        = 'Z_GET_CURRENT_LOCATION'
                                            iv_description = 'Get the current location'
                                            it_parameters  = gt_parameters ).
    CLEAR gt_parameters.
    gs_parameter-parameter_name = |Latitude|.
    gs_parameter-type = 'string'.
    gs_parameter-description = |Latitude|.
    gs_parameter-is_required = abap_true.
    APPEND gs_parameter TO gt_parameters.
    CLEAR gs_parameter.
    gs_parameter-parameter_name = |Longitude|.
    gs_parameter-type = 'string'.
    gs_parameter-description = |Longitude|.
    gs_parameter-is_required = abap_true.
    APPEND gs_parameter TO gt_parameters.
    CLEAR gs_parameter.
    lo_model_key->add_function_declaration( iv_name        = 'Z_GET_WEATHER_INFORMATION'
                                            iv_description = 'Gets weather information like temperature for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->add_function_declaration( iv_name        = 'Z_GET_CURRENT_AIR_QUALITY'
                                            iv_description = 'Gets weather information like temperature for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->add_function_declaration( iv_name        = 'GET_EARTHQUAKE_POSSIBILITY'
                                            iv_description = 'Gets possibility of Earthquake for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->add_function_declaration( iv_name        = 'GET_STORM_POSSIBILITY'
                                            iv_description = 'Gets possibility of a STORM for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->set_system_instructions(
      EXPORTING
        iv_text = gv_system_instruction
    ).
    DATA(lo_response) = lo_model_key->set_auto_invoke_sap_function( abap_true
                                  )->generate_content( iv_prompt_text = gv_prompt ).
    DATA(ls_response) = lo_response->get_response( ).
    /ui2/cl_json=>serialize(
      EXPORTING
        data   = ls_response-candidates[ 1 ]-content-parts           " Data to serialize
      RECEIVING
        r_json = DATA(lv_json_string)                 " JSON string
    ).
    IF lv_json_string IS NOT INITIAL.
      CLEAR gv_output.
      gv_output = lv_json_string.
    ENDIF.
  CATCH /goog/cx_sdk INTO DATA(lo_cx_sdk).
  cl_demo_output=>display( lo_cx_sdk->get_text( ) ).
ENDTRY.
lo_model_key->close( ).
CLEAR lo_model_key.
CLEAR lo_response.
CLEAR ls_response.

Claude

gv_prompt = 'Get the air quality in my current location'.
gv_system_instruction = 'You are a helpful weather assistant bot. You can turn find my location and get the weather information like temperature' &&
'You can also alert me about EarthQuakes and Storm.' &&
'You can also provide me information on Air Quality based on a location' &&
'Do not perform any other tasks.'.
TRY.
    DATA(lo_model_key) = NEW /goog//goog/cl_model_claude( iv_model_key = 'claude' ).
    gv_final_op = lo_model_key->gs_ai_config-model_id.
    lo_model_key->add_function_declaration( iv_name        = 'Z_GET_CURRENT_LOCATION'
                                            iv_description = 'Get the current location'
                                            it_parameters  = gt_parameters ).
    CLEAR gt_parameters.
    gs_parameter-parameter_name = |Latitude|.
    gs_parameter-type = 'string'.
    gs_parameter-description = |Latitude|.
    gs_parameter-is_required = abap_true.
    APPEND gs_parameter TO gt_parameters.
    CLEAR gs_parameter.
    gs_parameter-parameter_name = |Longitude|.
    gs_parameter-type = 'string'.
    gs_parameter-description = |Longitude|.
    gs_parameter-is_required = abap_true.
    APPEND gs_parameter TO gt_parameters.
    CLEAR gs_parameter.
    lo_model_key->add_function_declaration( iv_name        = 'Z_GET_WEATHER_INFORMATION'
                                            iv_description = 'Gets weather information like temperature for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->add_function_declaration( iv_name        = 'Z_GET_CURRENT_AIR_QUALITY'
                                            iv_description = 'Gets weather information like temperature for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->add_function_declaration( iv_name        = 'GET_EARTHQUAKE_POSSIBILITY'
                                            iv_description = 'Gets possibility of Earthquake for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->add_function_declaration( iv_name        = 'GET_STORM_POSSIBILITY'
                                            iv_description = 'Gets possibility of a STORM for a given location which is latitude and longitude'
                                            it_parameters  = gt_parameters ).
    lo_model_key->set_system_instructions(
      EXPORTING
        iv_text = gv_system_instruction
    ).
    DATA(lo_response) = lo_model_key->set_auto_invoke_sap_function( abap_true
                                  )->generate_content( iv_prompt_text = gv_prompt ).
    DATA(ls_response) = lo_response->get_response( ).
    /ui2/cl_json=>serialize(
      EXPORTING
        data   = ls_response-candidates[ 1 ]-content-parts           " Data to serialize
      RECEIVING
        r_json = DATA(lv_json_string)                 " JSON string
    ).
    IF lv_json_string IS NOT INITIAL.
      CLEAR gv_output.
      gv_output = lv_json_string.
    ENDIF.
  CATCH /goog/cx_sdk INTO DATA(lo_cx_sdk).
  cl_demo_output=>display( lo_cx_sdk->get_text( ) ).
ENDTRY.
lo_model_key->close( ).
CLEAR lo_model_key.
CLEAR lo_response.
CLEAR ls_response.

如要停用自動函式鏈結,並只從 LLM 取得第一個函式的回應,請使用 SET_FUNCTION_CALLING_CONFIG 方法,並將 IV_DISABLE_FUNCTION_CHAINING 參數設為 ABAP_TRUE。例如:


      lo_model_key->set_function_calling_config( iv_disable_function_chaining = abap_true ).
      DATA(lo_response) = lo_model_key->set_auto_invoke_sap_function( abap_true
                                     )->generate_content( iv_prompt_text = gv_prompt ).

如要取得 SDK 叫用的所有函式模組,以及傳遞給這些模組的參數,請呼叫 GET_ALL_FUNCTION_CALLS 方法:

      DATA(lo_response) = lo_model_key->set_auto_invoke_sap_function( abap_true
                                     )->generate_content( iv_prompt_text = gv_prompt ).

      DATA(ls_response) = lo_response->get_all_function_calls( ).

後續步驟