SAP AI Core avec ABAP Cloud : Intégrer les services IA

Catégorie
Integration
Publié
Auteur
Johannes

SAP AI Core est l’infrastructure IA centrale de la SAP Business Technology Platform (BTP). Avec ABAP Cloud, vous pouvez intégrer directement des services IA tels que la classification de texte, la reconnaissance d’entités nommées, la génération d’embeddings ou les modèles d’IA générative dans vos applications métier.

Qu’est-ce que SAP AI Core ?

SAP AI Core est un service pour l’exécution et la gestion de modèles de Machine Learning sur BTP. Il offre :

FonctionnalitéDescription
Model ServingHébergement et mise à l’échelle de modèles ML
SAP AI ServicesServices IA préfabriqués (Document Extraction, etc.)
Generative AI HubAccès aux LLMs (GPT, Claude, etc.)
Custom ModelsEntraîner et déployer vos propres modèles
MLOpsVersioning, monitoring, gestion du cycle de vie

Aperçu de l’architecture

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

Services IA disponibles

SAP AI Business Services

ServiceDescriptionCas d’utilisation
Document Information ExtractionAnalyser des documents et extraire des donnéesTraitement de factures
Business Entity RecognitionReconnaître des entités dans les textesClassifier les demandes clients
Service Ticket IntelligenceCatégoriser et router les ticketsAutomatisation du helpdesk
Data Attribute RecommendationSuggérer des attributsMaintenance des données de base

Generative AI Hub

Le Generative AI Hub offre l’accès aux Large Language Models (LLMs) :

Famille de modèlesExemplesUtilisation
OpenAI GPTGPT-4, GPT-3.5-turboGénération de texte, analyse
Anthropic ClaudeClaude 3 Opus/SonnetAnalyse de documents, codage
GoogleGemini ProApplications multimodales
Embeddingstext-embedding-ada-002Recherche sémantique, RAG

Configuration et paramétrage

1. Créer une instance de service AI Core

Dans le BTP Cockpit sous Service Marketplace :

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

2. Générer une clé de service

Créez une clé de service pour l’authentification :

{
"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. Configurer la destination

Créez une destination dans le BTP Cockpit :

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

4. Communication Arrangement

Créez un Communication Arrangement dans le système ABAP :

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

Appeler le service SAP AI Core

Classe client de base

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.
" Créer le JSON de la requête
DATA(lv_json) = /ui2/cl_json=>serialize(
data = is_request
compress = abap_true
pretty_name = /ui2/cl_json=>pretty_mode-camel_case ).
" Appeler l'API (Endpoint Gen AI Hub)
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 ).
" Parser la réponse
/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 ).
" Définir l'en-tête AI-Resource-Group
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( ).
" Logger l'erreur et lever une exception
RAISE EXCEPTION TYPE cx_web_http_client_error.
ENDIF.
lo_client->close( ).
ENDMETHOD.
ENDCLASS.

Exemples pratiques

Exemple 1 : Classification de texte

Classifiez automatiquement les demandes clients entrantes :

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( ).
" Prompt système pour la classification
DATA(lv_system_prompt) = |Tu es un système de classification de tickets. | &&
|Analyse la demande client et retourne la classification en JSON.\n| &&
|Catégories: BILLING, TECHNICAL, SALES, GENERAL\n| &&
|Priorités: HIGH, MEDIUM, LOW\n| &&
|Format de réponse: \{"category": "...", "priority": "...", "confidence": 0.0-1.0\}|.
" Construire la requête
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 )
)
).
" Appeler l'IA
DATA(ls_response) = lo_client->chat_completion( ls_request ).
" Parser la réponse
IF lines( ls_response-choices ) > 0.
DATA(lv_content) = ls_response-choices[ 1 ]-message-content.
" Extraire et parser le JSON de la réponse
/ui2/cl_json=>deserialize(
EXPORTING json = lv_content
CHANGING data = rs_result ).
ENDIF.
ENDMETHOD.
ENDCLASS.

Utilisation dans une détermination RAP :

METHOD classify_on_create.
" Lire les nouveaux tickets
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.
" Classifier le ticket
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.
" Gérer l'erreur - définir des valeurs par défaut
APPEND VALUE #(
%tky = ls_ticket-%tky
category = 'GENERAL"
priority = 'MEDIUM"
) TO lt_update.
ENDTRY.
ENDLOOP.
" Mettre à jour les tickets
MODIFY ENTITIES OF zi_ticket IN LOCAL MODE
ENTITY Ticket
UPDATE FIELDS ( category priority )
WITH lt_update.
ENDMETHOD.

Exemple 2 : Extraction de texte à partir de documents

Extrayez des données structurées à partir de texte libre :

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) =
|Tu es un système d'analyse de documents. Extrais les données de facture | &&
|du texte suivant et retourne-les en JSON.\n| &&
|Schéma: \{\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": ["Description Quantité Prix", ...]\n| &&
|\}\n| &&
|Retourne uniquement le JSON, pas d'explications.|.
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.
" Nettoyer le JSON (supprimer les blocs de code Markdown si présents)
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.

Exemple 3 : Génération d’embeddings pour la recherche sémantique

Créez des embeddings pour une recherche vectorielle :

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 ).
" Corps de la requête
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( ).
" Parser la réponse
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.
" Traitement par lots pour plusieurs textes
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.
" Calculer la similarité cosinus
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.

Application : Recherche sémantique de produits

METHOD search_similar_products.
DATA(lo_embedding_svc) = NEW zcl_embedding_service( ).
" Générer l'embedding pour la requête de recherche
DATA(lt_query_embedding) = lo_embedding_svc->generate_embedding( iv_search_query ).
" Charger les produits avec leurs embeddings stockés
SELECT product_id, name, embedding_json
FROM zproduct_embeddings
INTO TABLE @DATA(lt_products).
" Calculer les similarités
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.
" Trier par similarité
SORT lt_results BY similarity DESCENDING.
" Retourner le top 10
rt_result = VALUE #( FOR i = 1 WHILE i <= 10 ( lt_results[ i ] ) ).
ENDMETHOD.

Exemple 4 : Assistant intelligent dans RAP

Intégrez un assistant IA comme action RAP :

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
{
// ... opérations standard ...
// Action Assistant IA
static action askAssistant
parameter ZA_AssistantQuery
result [1] ZA_AssistantResponse;
}

Behavior Implementation :

METHOD askAssistant.
DATA(lo_client) = NEW zcl_ai_core_client( ).
" Construire le contexte à partir des données système
DATA(lv_system_context) =
|Tu es un assistant commercial pour un système SAP. | &&
|Réponds aux questions sur les commandes clients, les produits et les prix. | &&
|Réponds de manière précise et professionnelle. Si tu n'es pas sûr, dis-le.|.
" Requête utilisateur avec contexte
DATA(lv_user_query) = keys[ 1 ]-%param-question.
DATA(lv_context) = keys[ 1 ]-%param-context.
IF lv_context IS NOT INITIAL.
lv_user_query = |Contexte: { lv_context }\n\nQuestion: { 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 = |Erreur: { lx_error->get_text( ) }|
confidence = '0.00"
sources = '"
)
) ).
ENDTRY.
ENDMETHOD.

Traitement des réponses

Forcer des réponses structurées

Pour obtenir des données structurées de manière fiable, utilisez le mode JSON ou des instructions claires :

METHOD get_structured_response.
DATA(lv_system_prompt) =
|Tu es un système d'extraction de données. | &&
|Réponds TOUJOURS avec un JSON valide dans le format suivant:\n| &&
|\{"field1": "value1", "field2": "value2"\}\n| &&
|Pas d'explications, uniquement du JSON.|.
DATA(ls_request) = VALUE zcl_ai_core_client=>ty_chat_request(
model = 'gpt-4"
max_tokens = 500
temperature = '0.0' " Température basse pour une sortie cohérente
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.
" Nettoyage JSON
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.
" Désérialiser
/ui2/cl_json=>deserialize(
EXPORTING json = lv_content
CHANGING data = rs_result ).
ENDIF.
ENDMETHOD.

Surveiller la consommation de tokens

METHOD log_token_usage.
DATA(ls_response) = mo_client->chat_completion( is_request ).
" Logger la consommation de tokens
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 }|.
" Écrire dans le log applicatif
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.

Gestion des erreurs

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.

Appels API robustes :

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. " Succès
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.
" Backoff exponentiel
DATA(lv_wait) = 1000 * lv_retries * lv_retries.
cl_abap_session=>sleep( lv_wait ).
ENDTRY.
ENDWHILE.
ENDMETHOD.

Bonnes pratiques

ThèmeRecommandation
PromptsPrompts clairs et structurés avec des exemples pour des résultats cohérents
TempératureBasse (0.0-0.3) pour les tâches déterministes, plus haute pour les tâches créatives
Limites de tokensLimiter max_tokens pour contrôler les coûts
Gestion des erreursImplémenter une logique de retry avec backoff exponentiel
Mise en cacheMettre en cache les requêtes répétées (ex. embeddings)
LoggingLogger la consommation de tokens et la latence pour le monitoring
FallbacksToujours prévoir une logique de secours pour les pannes IA
Protection des donnéesNe pas envoyer de données sensibles aux LLMs externes
CoûtsUtiliser des modèles moins chers (GPT-3.5) pour les tâches simples
TestsTester les composants IA avec des réponses mock

Sujets connexes