8. L'intelligence artificielle
This content is not available in your language yet.
Oui, votre module peut appeler un modèle de langage. Non, il ne peut pas appeler un fournisseur directement.
from kewos.ai import AiMessage, AiRequest, completeLa distinction n’est pas une formalité : tout ce qui rend un appel d’IA acceptable en entreprise vit dans la façade, et vous en héritez uniquement en passant par elle.
Ce que la façade fait pour vous
| L’activation | Si le client n’a pas activé l’IA, l’appel est refusé. Pas de contournement possible. |
| La liste blanche | Seuls les fournisseurs que le client a autorisés sont joignables. |
| La résidence des données | Un fournisseur hors Union européenne exige un consentement explicite du client. Sans lui, l’appel est refusé. |
| Le quota | Un budget d’appels par fenêtre de temps, par client. |
| L’audit | Chaque appel est tracé. |
| Le cache | Deux fois la même question ne se paie pas deux fois. |
| Le choix du modèle | Le client choisit son fournisseur ; votre code n’en connaît aucun. |
Un module qui appellerait une API de fournisseur en direct perdrait les sept. C’est pourquoi c’est interdit, pas parce qu’on aime les règles.
Un appel
from kewos.ai import AiMessage, AiRequest, completefrom kewos.ai.exceptions import AiDisabledError, AiQuotaExceededError, AiResidencyErrorfrom kewos.secrets import build_tenant_secrets_backend
def summarise_blurb(engine, blurb: str) -> str | None: """Turn a publisher blurb into one sentence for the catalogue.""" request = AiRequest( messages=(AiMessage(role="user", content=f"Summarise in one sentence:\n\n{blurb}"),), system="Answer in a single sentence. No preamble, no commentary.", max_tokens=200, ) try: response = complete( engine, request, secrets=build_tenant_secrets_backend(engine), ) except AiDisabledError: return None # AI is off for this tenant: not a failure except (AiQuotaExceededError, AiResidencyError): return None # a legitimate refusal: degrade, do not break return response.textOù faire cet appel
Pas dans une requête HTTP. Un appel de modèle prend des secondes et part sur le réseau. Mettez-le dans un traitement de fond.
from kewos.jobs import job
@job(queue="default")def summarise_title(title_id: int) -> None: """Fill in the summary of one catalogue entry, out of band.""" ...Le déclencheur naturel est un événement du module, ou une tâche planifiée qui traite un lot.
Un modèle qui voit
Pour une image, un bloc dédié remplace le texte :
from kewos.ai.provider import AiImageBlock, AiTextBlock
message = AiMessage( role="user", content=( AiImageBlock(media_type="image/png", data=base64_de_l_image), AiTextBlock(text="Which book cover is this? Give the title and author."), ),)Pour transcrire un document plutôt que le commenter, ne le faites pas vous-même : passez par
kewos/ocr, qui gère le choix du moteur et le repli.
Faire écrire des données par un modèle
Un modèle de langage ne doit jamais écrire directement dans votre base. Le schéma est : proposer, puis confirmer.
- Le modèle produit une proposition structurée, contrainte par un schéma.
- Vous la validez comme n’importe quelle entrée utilisateur.
- Vous la présentez à l’utilisateur.
- L’utilisateur confirme, et c’est votre code qui écrit.
request = AiRequest( messages=(...), response_format="json", # constrain the reply to a valid JSON object max_tokens=800,)Une proposition non confirmée n’a produit aucun effet de bord. C’est ce qui rend la fonctionnalité rattrapable le jour où le modèle se trompe, et il se trompera.
Ce qui n’existe pas encore
Déclarer un prompt dans une vue ou dans une action YAML. Le format déclaratif ne connaît aujourd’hui que deux opérations, affecter une valeur et émettre un événement. Un module en YAML ne peut donc pas appeler un modèle sans passer par du code.
C’est une limite identifiée, et une décision d’architecture est en cours de rédaction pour la lever. En attendant, un module YAML qui a besoin d’IA s’accompagne d’un petit module en code qui expose l’appel.