SAP AI Core mit ABAP Cloud: KI-Services integrieren

kategorie
Integration
Veröffentlicht
autor
Johannes

SAP AI Core ist die zentrale KI-Infrastruktur in der SAP Business Technology Platform (BTP). Mit ABAP Cloud kannst du KI-Services wie Textklassifizierung, Named Entity Recognition, Embedding-Generierung oder generative AI-Modelle direkt in deine Geschäftsanwendungen integrieren.

Was ist SAP AI Core?

SAP AI Core ist ein Service zur Ausführung und Verwaltung von Machine-Learning-Modellen auf der BTP. Er bietet:

FeatureBeschreibung
Model ServingHosting und Skalierung von ML-Modellen
SAP AI ServicesVorgefertigte KI-Services (Document Extraction, etc.)
Generative AI HubZugang zu LLMs (GPT, Claude, etc.)
Custom ModelsEigene Modelle trainieren und deployen
MLOpsVersionierung, Monitoring, Lifecycle Management

Architektur-Übersicht

┌─────────────────────────────────────────────────────────────────────┐
│ SAP BTP │
│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │
│ │ ABAP Cloud │ │ Destination │ │ SAP AI Core │ │
│ │ │──>│ Service │──>│ │ │
│ │ ┌───────────┐ │ │ │ │ ┌───────────┐ │ │
│ │ │ RAP App │ │ │ ┌───────────┐ │ │ │ Gen AI Hub│ │ │
│ │ │ │ │ │ │ AI Core │ │ │ │ (LLMs) │ │ │
│ │ │ AI Client │──────│ │ Destination│──────│ ├───────────┤ │ │
│ │ │ │ │ │ └───────────┘ │ │ │ ML Models │ │ │
│ │ └───────────┘ │ │ │ │ │ (Custom) │ │ │
│ │ │ │ │ │ └───────────┘ │ │
│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘

Verfügbare KI-Services

SAP AI Business Services

ServiceBeschreibungUse Case
Document Information ExtractionDokumente analysieren und Daten extrahierenRechnungsverarbeitung
Business Entity RecognitionEntitäten in Texten erkennenKundenanfragen klassifizieren
Service Ticket IntelligenceTickets kategorisieren und routenHelpdesk-Automatisierung
Data Attribute RecommendationAttribute vorschlagenStammdatenpflege

Generative AI Hub

Der Generative AI Hub bietet Zugang zu Large Language Models (LLMs):

Modell-FamilieBeispieleEinsatz
OpenAI GPTGPT-4, GPT-3.5-turboTextgenerierung, Analyse
Anthropic ClaudeClaude 3 Opus/SonnetDokumentenanalyse, Coding
GoogleGemini ProMultimodale Anwendungen
Embeddingstext-embedding-ada-002Semantische Suche, RAG

Setup und Konfiguration

1. AI Core Service Instance erstellen

Im BTP Cockpit unter Service Marketplace:

┌──────────────────────────────────────────────────────────────┐
│ Service Instance Configuration │
├──────────────────────────────────────────────────────────────┤
│ Service: SAP AI Core │
│ Plan: standard (oder extended) │
│ Instance Name: ai-core-instance │
│ │
│ Parameters (JSON): │
│ { │
│ "servicePlanName": "standard" │
│ } │
└──────────────────────────────────────────────────────────────┘

2. Service Key generieren

Erstelle einen Service Key für die Authentifizierung:

{
"clientid": "sb-ai-core-xxx",
"clientsecret": "***",
"url": "https://ai-core.cfapps.eu10.hana.ondemand.com",
"serviceurls": {
"AI_API_URL": "https://api.ai.prod.eu-central-1.aws.ml.hana.ondemand.com"
},
"appname": "ai-core-xxx",
"identityzone": "my-subaccount"
}

3. Destination konfigurieren

Erstelle eine Destination im BTP Cockpit:

┌──────────────────────────────────────────────────────────────┐
│ Destination: SAP_AI_CORE │
├──────────────────────────────────────────────────────────────┤
│ Name: SAP_AI_CORE │
│ Type: HTTP │
│ URL: <AI_API_URL aus Service Key> │
│ Proxy Type: Internet │
│ Authentication: OAuth2ClientCredentials │
│ │
│ Token Service URL: <url aus Service Key>/oauth/token │
│ Client ID: <clientid aus Service Key> │
│ Client Secret: <clientsecret aus Service Key> │
│ │
│ Additional Properties: │
│ ├── AI-Resource-Group: default │
│ └── URL.headers.AI-Resource-Group: default │
└──────────────────────────────────────────────────────────────┘

4. Communication Arrangement

Im ABAP-System ein Communication Arrangement anlegen:

Communication Scenario: SAP_COM_0276 (Destination Service Integration)
Communication System: BTP_DESTINATION_SERVICE
Outbound Services: Destination Service API → Active

SAP AI Core Service aufrufen

Basis-Client-Klasse

CLASS zcl_ai_core_client DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_message,
role TYPE string,
content TYPE string,
END OF ty_message,
tt_messages TYPE STANDARD TABLE OF ty_message WITH EMPTY KEY,
BEGIN OF ty_chat_request,
model TYPE string,
messages TYPE tt_messages,
max_tokens TYPE i,
temperature TYPE decfloat16,
END OF ty_chat_request,
BEGIN OF ty_choice,
index TYPE i,
message TYPE ty_message,
END OF ty_choice,
tt_choices TYPE STANDARD TABLE OF ty_choice WITH EMPTY KEY,
BEGIN OF ty_usage,
prompt_tokens TYPE i,
completion_tokens TYPE i,
total_tokens TYPE i,
END OF ty_usage,
BEGIN OF ty_chat_response,
id TYPE string,
object TYPE string,
created TYPE i,
model TYPE string,
choices TYPE tt_choices,
usage TYPE ty_usage,
END OF ty_chat_response.
METHODS constructor
RAISING cx_http_dest_provider_error.
METHODS chat_completion
IMPORTING is_request TYPE ty_chat_request
RETURNING VALUE(rs_result) TYPE ty_chat_response
RAISING cx_web_http_client_error.
PRIVATE SECTION.
DATA mo_destination TYPE REF TO if_http_destination.
DATA mv_resource_group TYPE string VALUE 'default'.
METHODS execute_request
IMPORTING iv_path TYPE string
iv_method TYPE i
iv_body TYPE string
RETURNING VALUE(rv_result) TYPE string
RAISING cx_web_http_client_error.
ENDCLASS.
CLASS zcl_ai_core_client IMPLEMENTATION.
METHOD constructor.
mo_destination = cl_http_destination_provider=>create_by_cloud_destination(
i_name = 'SAP_AI_CORE'
i_authn_mode = if_a4c_cp_service=>service_specific ).
ENDMETHOD.
METHOD chat_completion.
" Request JSON erstellen
DATA(lv_json) = /ui2/cl_json=>serialize(
data = is_request
compress = abap_true
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
" API aufrufen (Gen AI Hub Endpoint)
DATA(lv_response) = execute_request(
iv_path = '/v2/inference/deployments/<deployment-id>/chat/completions'
iv_method = if_web_http_client=>post
iv_body = lv_json ).
" Response parsen
/ui2/cl_json=>deserialize(
EXPORTING json = lv_response
CHANGING data = rs_result ).
ENDMETHOD.
METHOD execute_request.
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination(
i_destination = mo_destination ).
DATA(lo_request) = lo_client->get_http_request( ).
lo_request->set_uri_path( iv_path ).
" AI-Resource-Group Header setzen
lo_request->set_header_field(
i_name = 'AI-Resource-Group'
i_value = mv_resource_group ).
IF iv_body IS NOT INITIAL.
lo_request->set_text( iv_body ).
lo_request->set_header_field(
i_name = 'Content-Type'
i_value = 'application/json' ).
ENDIF.
DATA(lo_response) = lo_client->execute( iv_method ).
DATA(lv_status) = lo_response->get_status( )-code.
IF lv_status >= 200 AND lv_status < 300.
rv_result = lo_response->get_text( ).
ELSE.
DATA(lv_error) = lo_response->get_text( ).
lo_client->close( ).
" Fehler loggen und Exception werfen
RAISE EXCEPTION TYPE cx_web_http_client_error.
ENDIF.
lo_client->close( ).
ENDMETHOD.
ENDCLASS.

Praktische Beispiele

Beispiel 1: Textklassifizierung

Klassifiziere eingehende Kundenanfragen automatisch:

CLASS zcl_ticket_classifier DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_classification,
category TYPE string,
priority TYPE string,
confidence TYPE decfloat16,
END OF ty_classification.
METHODS classify_ticket
IMPORTING iv_ticket_text TYPE string
RETURNING VALUE(rs_result) TYPE ty_classification
RAISING cx_http_dest_provider_error
cx_web_http_client_error.
ENDCLASS.
CLASS zcl_ticket_classifier IMPLEMENTATION.
METHOD classify_ticket.
DATA(lo_client) = NEW zcl_ai_core_client( ).
" System-Prompt für Klassifizierung
DATA(lv_system_prompt) = |Du bist ein Ticket-Klassifizierungssystem. | &&
|Analysiere die Kundenanfrage und gib die Klassifizierung als JSON zurück.\n| &&
|Kategorien: BILLING, TECHNICAL, SALES, GENERAL\n| &&
|Prioritäten: HIGH, MEDIUM, LOW\n| &&
|Antwortformat: \{"category": "...", "priority": "...", "confidence": 0.0-1.0\}|.
" Request aufbauen
DATA(ls_request) = VALUE zcl_ai_core_client=>ty_chat_request(
model = 'gpt-4'
max_tokens = 100
temperature = '0.1'
messages = VALUE #(
( role = 'system' content = lv_system_prompt )
( role = 'user' content = iv_ticket_text )
)
).
" AI aufrufen
DATA(ls_response) = lo_client->chat_completion( ls_request ).
" Antwort parsen
IF lines( ls_response-choices ) > 0.
DATA(lv_content) = ls_response-choices[ 1 ]-message-content.
" JSON aus Antwort extrahieren und parsen
/ui2/cl_json=>deserialize(
EXPORTING json = lv_content
CHANGING data = rs_result ).
ENDIF.
ENDMETHOD.
ENDCLASS.

Nutzung in einer RAP-Determination:

METHOD classify_on_create.
" Neue Tickets lesen
READ ENTITIES OF zi_ticket IN LOCAL MODE
ENTITY Ticket
FIELDS ( description )
WITH CORRESPONDING #( keys )
RESULT DATA(lt_tickets).
DATA lt_update TYPE TABLE FOR UPDATE zi_ticket\\Ticket.
LOOP AT lt_tickets INTO DATA(ls_ticket).
TRY.
" Ticket klassifizieren
DATA(lo_classifier) = NEW zcl_ticket_classifier( ).
DATA(ls_class) = lo_classifier->classify_ticket( ls_ticket-description ).
APPEND VALUE #(
%tky = ls_ticket-%tky
category = ls_class-category
priority = ls_class-priority
) TO lt_update.
CATCH cx_root.
" Fehler behandeln - Standardwerte setzen
APPEND VALUE #(
%tky = ls_ticket-%tky
category = 'GENERAL'
priority = 'MEDIUM'
) TO lt_update.
ENDTRY.
ENDLOOP.
" Tickets aktualisieren
MODIFY ENTITIES OF zi_ticket IN LOCAL MODE
ENTITY Ticket
UPDATE FIELDS ( category priority )
WITH lt_update.
ENDMETHOD.

Beispiel 2: Text-Extraktion aus Dokumenten

Extrahiere strukturierte Daten aus Freitext:

CLASS zcl_document_extractor DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
BEGIN OF ty_address,
street TYPE string,
city TYPE string,
zip TYPE string,
country TYPE string,
END OF ty_address,
BEGIN OF ty_invoice_data,
invoice_number TYPE string,
invoice_date TYPE string,
vendor_name TYPE string,
vendor_address TYPE ty_address,
total_amount TYPE decfloat16,
currency TYPE string,
line_items TYPE STANDARD TABLE OF string WITH EMPTY KEY,
END OF ty_invoice_data.
METHODS extract_invoice_data
IMPORTING iv_document_text TYPE string
RETURNING VALUE(rs_result) TYPE ty_invoice_data
RAISING cx_http_dest_provider_error
cx_web_http_client_error.
ENDCLASS.
CLASS zcl_document_extractor IMPLEMENTATION.
METHOD extract_invoice_data.
DATA(lo_client) = NEW zcl_ai_core_client( ).
DATA(lv_system_prompt) =
|Du bist ein Dokumentenanalyse-System. Extrahiere die Rechnungsdaten | &&
|aus dem folgenden Text und gib sie als JSON zurück.\n| &&
|Schema: \{\n| &&
| "invoice_number": "string",\n| &&
| "invoice_date": "YYYY-MM-DD",\n| &&
| "vendor_name": "string",\n| &&
| "vendor_address": \{"street": "", "city": "", "zip": "", "country": ""\},\n| &&
| "total_amount": number,\n| &&
| "currency": "EUR/USD/etc",\n| &&
| "line_items": ["Beschreibung Menge Preis", ...]\n| &&
|\}\n| &&
|Gib nur das JSON zurück, keine Erklärungen.|.
DATA(ls_request) = VALUE zcl_ai_core_client=>ty_chat_request(
model = 'gpt-4'
max_tokens = 1000
temperature = '0.0'
messages = VALUE #(
( role = 'system' content = lv_system_prompt )
( role = 'user' content = iv_document_text )
)
).
DATA(ls_response) = lo_client->chat_completion( ls_request ).
IF lines( ls_response-choices ) > 0.
DATA(lv_json) = ls_response-choices[ 1 ]-message-content.
" JSON bereinigen (Markdown Code-Blöcke entfernen falls vorhanden)
REPLACE ALL OCCURRENCES OF '```json' IN lv_json WITH ``.
REPLACE ALL OCCURRENCES OF '```' IN lv_json WITH ``.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_json
CHANGING data = rs_result ).
ENDIF.
ENDMETHOD.
ENDCLASS.

Beispiel 3: Embedding-Generierung für Semantische Suche

Erstelle Embeddings für eine Vektor-Suche:

CLASS zcl_embedding_service DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
TYPES:
tt_embedding TYPE STANDARD TABLE OF decfloat16 WITH EMPTY KEY,
BEGIN OF ty_embedding_result,
text TYPE string,
embedding TYPE tt_embedding,
END OF ty_embedding_result,
tt_embedding_results TYPE STANDARD TABLE OF ty_embedding_result WITH EMPTY KEY.
METHODS generate_embedding
IMPORTING iv_text TYPE string
RETURNING VALUE(rt_result) TYPE tt_embedding
RAISING cx_http_dest_provider_error
cx_web_http_client_error.
METHODS generate_embeddings
IMPORTING it_texts TYPE string_table
RETURNING VALUE(rt_result) TYPE tt_embedding_results
RAISING cx_http_dest_provider_error
cx_web_http_client_error.
METHODS calculate_similarity
IMPORTING it_embedding1 TYPE tt_embedding
it_embedding2 TYPE tt_embedding
RETURNING VALUE(rv_result) TYPE decfloat16.
ENDCLASS.
CLASS zcl_embedding_service IMPLEMENTATION.
METHOD generate_embedding.
DATA(lo_destination) = cl_http_destination_provider=>create_by_cloud_destination(
i_name = 'SAP_AI_CORE'
i_authn_mode = if_a4c_cp_service=>service_specific ).
DATA(lo_client) = cl_web_http_client_manager=>create_by_http_destination(
i_destination = lo_destination ).
" Request Body
DATA: BEGIN OF ls_request,
model TYPE string VALUE 'text-embedding-ada-002',
input TYPE string,
END OF ls_request.
ls_request-input = iv_text.
DATA(lv_json) = /ui2/cl_json=>serialize(
data = ls_request
compress = abap_true
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
DATA(lo_request) = lo_client->get_http_request( ).
lo_request->set_uri_path( '/v2/inference/deployments/<deployment-id>/embeddings' ).
lo_request->set_header_field( i_name = 'AI-Resource-Group' i_value = 'default' ).
lo_request->set_header_field( i_name = 'Content-Type' i_value = 'application/json' ).
lo_request->set_text( lv_json ).
DATA(lo_response) = lo_client->execute( if_web_http_client=>post ).
IF lo_response->get_status( )-code = 200.
DATA(lv_response) = lo_response->get_text( ).
" Response parsen
DATA: BEGIN OF ls_response,
data TYPE STANDARD TABLE OF
BEGIN OF ls_data,
embedding TYPE tt_embedding,
END OF ls_data WITH EMPTY KEY,
END OF ls_response.
/ui2/cl_json=>deserialize(
EXPORTING json = lv_response
CHANGING data = ls_response ).
IF lines( ls_response-data ) > 0.
rt_result = ls_response-data[ 1 ]-embedding.
ENDIF.
ENDIF.
lo_client->close( ).
ENDMETHOD.
METHOD generate_embeddings.
" Batch-Verarbeitung für mehrere Texte
LOOP AT it_texts INTO DATA(lv_text).
DATA(lt_embedding) = generate_embedding( lv_text ).
APPEND VALUE #(
text = lv_text
embedding = lt_embedding
) TO rt_result.
ENDLOOP.
ENDMETHOD.
METHOD calculate_similarity.
" Kosinus-Ähnlichkeit berechnen
DATA: lv_dot_product TYPE decfloat16 VALUE 0,
lv_norm1 TYPE decfloat16 VALUE 0,
lv_norm2 TYPE decfloat16 VALUE 0.
DATA(lv_length) = lines( it_embedding1 ).
DO lv_length TIMES.
DATA(lv_idx) = sy-index.
DATA(lv_val1) = it_embedding1[ lv_idx ].
DATA(lv_val2) = it_embedding2[ lv_idx ].
lv_dot_product = lv_dot_product + ( lv_val1 * lv_val2 ).
lv_norm1 = lv_norm1 + ( lv_val1 * lv_val1 ).
lv_norm2 = lv_norm2 + ( lv_val2 * lv_val2 ).
ENDDO.
IF lv_norm1 > 0 AND lv_norm2 > 0.
rv_result = lv_dot_product / ( sqrt( lv_norm1 ) * sqrt( lv_norm2 ) ).
ENDIF.
ENDMETHOD.
ENDCLASS.

Anwendung: Semantische Produktsuche

METHOD search_similar_products.
DATA(lo_embedding_svc) = NEW zcl_embedding_service( ).
" Embedding für Suchanfrage generieren
DATA(lt_query_embedding) = lo_embedding_svc->generate_embedding( iv_search_query ).
" Produkte mit gespeicherten Embeddings laden
SELECT product_id, name, embedding_json
FROM zproduct_embeddings
INTO TABLE @DATA(lt_products).
" Ähnlichkeiten berechnen
DATA: BEGIN OF ls_result,
product_id TYPE string,
name TYPE string,
similarity TYPE decfloat16,
END OF ls_result,
lt_results LIKE STANDARD TABLE OF ls_result.
LOOP AT lt_products INTO DATA(ls_product).
DATA lt_product_embedding TYPE zcl_embedding_service=>tt_embedding.
/ui2/cl_json=>deserialize(
EXPORTING json = ls_product-embedding_json
CHANGING data = lt_product_embedding ).
DATA(lv_similarity) = lo_embedding_svc->calculate_similarity(
it_embedding1 = lt_query_embedding
it_embedding2 = lt_product_embedding ).
APPEND VALUE #(
product_id = ls_product-product_id
name = ls_product-name
similarity = lv_similarity
) TO lt_results.
ENDLOOP.
" Nach Ähnlichkeit sortieren
SORT lt_results BY similarity DESCENDING.
" Top 10 zurückgeben
rt_result = VALUE #( FOR i = 1 WHILE i <= 10 ( lt_results[ i ] ) ).
ENDMETHOD.

Beispiel 4: Intelligenter Assistent in RAP

Integriere einen KI-Assistenten als RAP Action:

define abstract entity ZA_AssistantQuery
{
question : abap.string(1000);
context : abap.string(5000);
}
define abstract entity ZA_AssistantResponse
{
answer : abap.string(5000);
confidence : abap.dec(5,2);
sources : abap.string(1000);
}

Behavior Definition:

managed implementation in class zbp_i_salesorder unique;
strict ( 2 );
define behavior for ZI_SalesOrder alias SalesOrder
{
// ... standard operations ...
// AI Assistant Action
static action askAssistant
parameter ZA_AssistantQuery
result [1] ZA_AssistantResponse;
}

Behavior Implementation:

METHOD askAssistant.
DATA(lo_client) = NEW zcl_ai_core_client( ).
" Kontext aus System-Daten aufbauen
DATA(lv_system_context) =
|Du bist ein Vertriebsassistent für ein SAP-System. | &&
|Beantworte Fragen zu Kundenaufträgen, Produkten und Preisen. | &&
|Antworte präzise und geschäftlich. Wenn du unsicher bist, sage es.|.
" User-Query mit Kontext
DATA(lv_user_query) = keys[ 1 ]-%param-question.
DATA(lv_context) = keys[ 1 ]-%param-context.
IF lv_context IS NOT INITIAL.
lv_user_query = |Kontext: { lv_context }\n\nFrage: { lv_user_query }|.
ENDIF.
TRY.
DATA(ls_request) = VALUE zcl_ai_core_client=>ty_chat_request(
model = 'gpt-4'
max_tokens = 500
temperature = '0.3'
messages = VALUE #(
( role = 'system' content = lv_system_context )
( role = 'user' content = lv_user_query )
)
).
DATA(ls_response) = lo_client->chat_completion( ls_request ).
IF lines( ls_response-choices ) > 0.
result = VALUE #( (
%cid = keys[ 1 ]-%cid
%param = VALUE #(
answer = ls_response-choices[ 1 ]-message-content
confidence = '0.85'
sources = 'SAP AI Core - GPT-4'
)
) ).
ENDIF.
CATCH cx_root INTO DATA(lx_error).
result = VALUE #( (
%cid = keys[ 1 ]-%cid
%param = VALUE #(
answer = |Fehler: { lx_error->get_text( ) }|
confidence = '0.00'
sources = ''
)
) ).
ENDTRY.
ENDMETHOD.

Response verarbeiten

Strukturierte Antworten erzwingen

Um zuverlässig strukturierte Daten zu erhalten, nutze JSON-Mode oder klare Anweisungen:

METHOD get_structured_response.
DATA(lv_system_prompt) =
|Du bist ein Datenextraktionssystem. | &&
|Antworte IMMER mit gültigem JSON im folgenden Format:\n| &&
|\{"field1": "value1", "field2": "value2"\}\n| &&
|Keine Erklärungen, nur JSON.|.
DATA(ls_request) = VALUE zcl_ai_core_client=>ty_chat_request(
model = 'gpt-4'
max_tokens = 500
temperature = '0.0' " Niedrige Temperatur für konsistente Ausgabe
messages = VALUE #(
( role = 'system' content = lv_system_prompt )
( role = 'user' content = iv_input )
)
).
DATA(ls_response) = mo_client->chat_completion( ls_request ).
IF lines( ls_response-choices ) > 0.
DATA(lv_content) = ls_response-choices[ 1 ]-message-content.
" JSON-Bereinigung
FIND REGEX '\{.*\}' IN lv_content MATCH OFFSET DATA(lv_offset) MATCH LENGTH DATA(lv_length).
IF sy-subrc = 0.
lv_content = substring( val = lv_content off = lv_offset len = lv_length ).
ENDIF.
" Deserialisieren
/ui2/cl_json=>deserialize(
EXPORTING json = lv_content
CHANGING data = rs_result ).
ENDIF.
ENDMETHOD.

Token-Verbrauch überwachen

METHOD log_token_usage.
DATA(ls_response) = mo_client->chat_completion( is_request ).
" Token-Verbrauch loggen
DATA(lv_log_message) = |AI Call: { ls_response-model } | &&
|Prompt: { ls_response-usage-prompt_tokens } | &&
|Completion: { ls_response-usage-completion_tokens } | &&
|Total: { ls_response-usage-total_tokens }|.
" In Application Log schreiben
cl_bali_log=>create_with_header(
EXPORTING
header = cl_bali_header_setter=>create(
object = 'ZAI_CORE'
subobject = 'USAGE' )
)->add_item(
item = cl_bali_message_setter=>create(
severity = if_bali_constants=>c_severity_information
text = lv_log_message )
)->save( ).
rs_result = ls_response.
ENDMETHOD.

Error Handling

CLASS zcx_ai_core_error DEFINITION
PUBLIC
INHERITING FROM cx_static_check
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_t100_message.
CONSTANTS:
BEGIN OF connection_failed,
msgid TYPE symsgid VALUE 'ZAI',
msgno TYPE symsgno VALUE '001',
attr1 TYPE scx_attrname VALUE 'MV_DESTINATION',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF connection_failed,
BEGIN OF rate_limit_exceeded,
msgid TYPE symsgid VALUE 'ZAI',
msgno TYPE symsgno VALUE '002',
attr1 TYPE scx_attrname VALUE '',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF rate_limit_exceeded,
BEGIN OF invalid_response,
msgid TYPE symsgid VALUE 'ZAI',
msgno TYPE symsgno VALUE '003',
attr1 TYPE scx_attrname VALUE 'MV_STATUS_CODE',
attr2 TYPE scx_attrname VALUE '',
attr3 TYPE scx_attrname VALUE '',
attr4 TYPE scx_attrname VALUE '',
END OF invalid_response.
DATA mv_destination TYPE string.
DATA mv_status_code TYPE i.
METHODS constructor
IMPORTING
textid LIKE if_t100_message=>t100key OPTIONAL
previous LIKE previous OPTIONAL
destination TYPE string OPTIONAL
status_code TYPE i OPTIONAL.
ENDCLASS.

Robuste API-Aufrufe:

METHOD call_ai_with_retry.
CONSTANTS: lc_max_retries TYPE i VALUE 3.
DATA: lv_retries TYPE i VALUE 0.
WHILE lv_retries < lc_max_retries.
TRY.
rs_result = mo_client->chat_completion( is_request ).
RETURN. " Erfolg
CATCH cx_web_http_client_error INTO DATA(lx_http).
lv_retries = lv_retries + 1.
IF lv_retries >= lc_max_retries.
RAISE EXCEPTION TYPE zcx_ai_core_error
EXPORTING
textid = zcx_ai_core_error=>connection_failed
previous = lx_http.
ENDIF.
" Exponentielles Backoff
DATA(lv_wait) = 1000 * lv_retries * lv_retries.
cl_abap_session=>sleep( lv_wait ).
ENDTRY.
ENDWHILE.
ENDMETHOD.

Best Practices

ThemaEmpfehlung
PromptsKlare, strukturierte Prompts mit Beispielen für konsistente Ergebnisse
TemperaturNiedrig (0.0-0.3) für deterministische Aufgaben, höher für kreative
Token-LimitsMax_tokens begrenzen, um Kosten zu kontrollieren
FehlerbehandlungRetry-Logik mit exponentiellem Backoff implementieren
CachingWiederholte Anfragen cachen (z.B. Embeddings)
LoggingToken-Verbrauch und Latenz für Monitoring loggen
FallbacksImmer Fallback-Logik für AI-Ausfälle vorsehen
DatenschutzKeine sensiblen Daten an externe LLMs senden
KostenGünstigere Modelle (GPT-3.5) für einfache Aufgaben nutzen
TestingAI-Komponenten mit Mock-Responses testen

Weiterführende Themen