|
|
""" |
|
|
Agent SWIFT: Génération et parsing de messages SWIFT structurés |
|
|
|
|
|
Cet agent démontre l'utilisation de PydanticAI pour: |
|
|
- Générer des messages SWIFT formatés depuis du texte naturel |
|
|
- Extraire les données structurées d'un message SWIFT |
|
|
- Valider la structure des messages SWIFT |
|
|
""" |
|
|
|
|
|
import asyncio |
|
|
import re |
|
|
from typing import Optional |
|
|
from pydantic import BaseModel, Field, field_validator |
|
|
from pydantic_ai import Agent, ModelSettings |
|
|
|
|
|
from app.models import finance_model |
|
|
|
|
|
|
|
|
try: |
|
|
from .swift_models import SWIFTMT103Structured, MT103Field32A |
|
|
from .swift_extractor import ( |
|
|
parse_swift_mt103_advanced, |
|
|
SwiftMT103Parsed, |
|
|
format_swift_mt103_from_parsed, |
|
|
) |
|
|
except ImportError: |
|
|
|
|
|
import sys |
|
|
from pathlib import Path |
|
|
sys.path.insert(0, str(Path(__file__).parent)) |
|
|
from swift_models import SWIFTMT103Structured, MT103Field32A |
|
|
from swift_extractor import ( |
|
|
parse_swift_mt103_advanced, |
|
|
SwiftMT103Parsed, |
|
|
format_swift_mt103_from_parsed, |
|
|
) |
|
|
|
|
|
|
|
|
swift_model_settings = ModelSettings( |
|
|
max_output_tokens=2000, |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
class SWIFTMT103(BaseModel): |
|
|
"""Message SWIFT MT103 - Transfert de fonds unique.""" |
|
|
|
|
|
|
|
|
message_type: str = Field(default="103", description="Type de message SWIFT (103)") |
|
|
sender_bic: str = Field(description="BIC de la banque émettrice (8 ou 11 caractères)") |
|
|
receiver_bic: str = Field(description="BIC de la banque réceptrice (8 ou 11 caractères)") |
|
|
|
|
|
|
|
|
value_date: str = Field(description="Date de valeur au format YYYYMMDD") |
|
|
currency: str = Field(description="Code devise ISO (3 lettres)", min_length=3, max_length=3) |
|
|
amount: float = Field(description="Montant du transfert", gt=0) |
|
|
|
|
|
|
|
|
ordering_customer: str = Field(description="Données de l'ordre donneur (nom, adresse, compte)") |
|
|
beneficiary: str = Field(description="Données du bénéficiaire (nom, adresse, compte)") |
|
|
remittance_info: str | None = Field(default=None, description="Information pour le bénéficiaire") |
|
|
charges: str = Field(default="OUR", description="Frais: OUR, SHA, BEN") |
|
|
reference: str | None = Field(default=None, description="Référence du transfert") |
|
|
|
|
|
|
|
|
class SWIFTMT940(BaseModel): |
|
|
"""Message SWIFT MT940 - Relevé bancaire.""" |
|
|
|
|
|
message_type: str = Field(default="940", description="Type de message SWIFT (940)") |
|
|
account_identification: str = Field(description="Identification du compte (IBAN)") |
|
|
statement_number: str = Field(description="Numéro de relevé") |
|
|
opening_balance_date: str = Field(description="Date de solde d'ouverture YYYYMMDD") |
|
|
opening_balance: float = Field(description="Solde d'ouverture") |
|
|
opening_balance_indicator: str = Field(description="C (Crédit) ou D (Débit)") |
|
|
currency: str = Field(description="Code devise ISO (3 lettres)") |
|
|
transactions: list[dict[str, str | float]] = Field(description="Liste des transactions") |
|
|
|
|
|
|
|
|
|
|
|
swift_generator = Agent( |
|
|
finance_model, |
|
|
model_settings=swift_model_settings, |
|
|
system_prompt=( |
|
|
"Vous êtes un expert en messages SWIFT bancaires. " |
|
|
"Votre rôle est de générer des messages SWIFT correctement formatés " |
|
|
"à partir de descriptions en langage naturel. " |
|
|
"Les messages SWIFT doivent être conformes aux standards internationaux. " |
|
|
"Pour les montants, utilisez toujours le format numérique avec 2 décimales. " |
|
|
"Les BIC doivent être valides (8 ou 11 caractères alphanumériques). " |
|
|
"Répondez en français mais générez les messages SWIFT au format standard.\n\n" |
|
|
"Vous disposez de 2000 tokens pour générer des messages SWIFT complets et détaillés." |
|
|
), |
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
swift_parser = Agent( |
|
|
finance_model, |
|
|
model_settings=ModelSettings(max_output_tokens=2000), |
|
|
system_prompt=( |
|
|
"Vous êtes un expert en parsing de messages SWIFT bancaires. " |
|
|
"Votre rôle est d'extraire précisément toutes les informations " |
|
|
"à partir de messages SWIFT formatés (MT103, MT940, etc.).\n\n" |
|
|
"Instructions importantes:\n" |
|
|
"- Identifiez TOUS les champs SWIFT présents (même optionnels)\n" |
|
|
"- Pour le champ :32A:, extrayez séparément la date (YYYYMMDD), devise (3 lettres), et montant\n" |
|
|
"- Pour les champs :50K: et :59:, conservez toutes les lignes (nom, adresse, compte)\n" |
|
|
"- Les dates doivent être au format YYYYMMDD\n" |
|
|
"- Les montants doivent être numériques avec décimales\n" |
|
|
"- Les BIC doivent être extraits des champs :52A:, :56A:, etc. si présents\n" |
|
|
"- Répondez en JSON structuré pour faciliter le parsing" |
|
|
), |
|
|
) |
|
|
|
|
|
|
|
|
def format_swift_mt103(mt103: SWIFTMT103) -> str: |
|
|
"""Formate un message SWIFT MT103 selon les standards.""" |
|
|
lines = [] |
|
|
|
|
|
|
|
|
lines.append(f":20:{mt103.reference or 'NONREF'}") |
|
|
lines.append(f":23B:CRED") |
|
|
lines.append(f":32A:{mt103.value_date}{mt103.currency}{mt103.amount:.2f}") |
|
|
lines.append(f":50K:/{mt103.ordering_customer}") |
|
|
lines.append(f":59:/{mt103.beneficiary}") |
|
|
|
|
|
if mt103.remittance_info: |
|
|
lines.append(f":70:{mt103.remittance_info}") |
|
|
|
|
|
lines.append(f":71A:{mt103.charges}") |
|
|
|
|
|
return "\n".join(lines) |
|
|
|
|
|
|
|
|
class SWIFTExtractedMT103(BaseModel): |
|
|
"""Structure extraite d'un message SWIFT MT103.""" |
|
|
|
|
|
|
|
|
reference: str = Field(description="Référence du transfert (:20:)") |
|
|
|
|
|
|
|
|
instruction_code: str = Field(default="CRED", description="Code instruction (:23B:)") |
|
|
|
|
|
|
|
|
value_date: str = Field(description="Date de valeur YYYYMMDD") |
|
|
currency: str = Field(description="Code devise ISO 3 lettres") |
|
|
amount: float = Field(description="Montant", gt=0) |
|
|
|
|
|
|
|
|
ordering_customer: str = Field(description="Données ordonnateur (:50K: ou :50A:)") |
|
|
ordering_customer_account: Optional[str] = Field(default=None, description="Compte ordonnateur (IBAN)") |
|
|
|
|
|
|
|
|
ordering_bank_bic: Optional[str] = Field(default=None, description="BIC banque ordonnateur (:52A:)") |
|
|
ordering_bank_name: Optional[str] = Field(default=None, description="Nom banque ordonnateur (:52D:)") |
|
|
|
|
|
|
|
|
intermediary_bank_bic: Optional[str] = Field(default=None, description="BIC banque intermédiaire (:56A:)") |
|
|
intermediary_bank_name: Optional[str] = Field(default=None, description="Nom banque intermédiaire (:56D:)") |
|
|
|
|
|
|
|
|
beneficiary_bank_bic: Optional[str] = Field(default=None, description="BIC banque bénéficiaire (:57A:)") |
|
|
beneficiary_bank_name: Optional[str] = Field(default=None, description="Nom banque bénéficiaire (:57D:)") |
|
|
|
|
|
|
|
|
beneficiary: str = Field(description="Données bénéficiaire (:59: ou :59A:)") |
|
|
beneficiary_account: Optional[str] = Field(default=None, description="Compte bénéficiaire (IBAN)") |
|
|
|
|
|
|
|
|
remittance_info: Optional[str] = Field(default=None, description="Information bénéficiaire (:70:)") |
|
|
|
|
|
|
|
|
charges: str = Field(default="OUR", description="Frais: OUR/SHA/BEN (:71A:)") |
|
|
|
|
|
|
|
|
bank_to_bank_info: Optional[str] = Field(default=None, description="Info banque à banque (:72:)") |
|
|
|
|
|
@field_validator("value_date") |
|
|
def validate_date(cls, v): |
|
|
if len(v) != 8 or not v.isdigit(): |
|
|
raise ValueError(f"Date must be YYYYMMDD format, got: {v}") |
|
|
return v |
|
|
|
|
|
@field_validator("currency") |
|
|
def validate_currency(cls, v): |
|
|
if len(v) != 3 or not v.isalpha(): |
|
|
raise ValueError(f"Currency must be 3 letter ISO code, got: {v}") |
|
|
return v.upper() |
|
|
|
|
|
@field_validator("charges") |
|
|
def validate_charges(cls, v): |
|
|
valid = ["OUR", "SHA", "BEN"] |
|
|
if v not in valid: |
|
|
raise ValueError(f"Charges must be one of {valid}, got: {v}") |
|
|
return v |
|
|
|
|
|
|
|
|
def parse_swift_mt103(swift_text: str) -> SWIFTExtractedMT103: |
|
|
""" |
|
|
Parse un message SWIFT MT103 et extrait tous les champs avec validation. |
|
|
|
|
|
Gère: |
|
|
- Champs multi-lignes (:50K:, :59:, etc.) |
|
|
- Champs optionnels |
|
|
- Extraction des BIC et noms de banques |
|
|
- Validation des formats (dates, devises, montants) |
|
|
""" |
|
|
|
|
|
lines = [line.strip() for line in swift_text.strip().split("\n") if line.strip()] |
|
|
|
|
|
parsed_data = { |
|
|
"reference": "NONREF", |
|
|
"instruction_code": "CRED", |
|
|
"charges": "OUR", |
|
|
} |
|
|
|
|
|
i = 0 |
|
|
while i < len(lines): |
|
|
line = lines[i] |
|
|
|
|
|
|
|
|
if line.startswith(":20:"): |
|
|
parsed_data["reference"] = line[4:].strip() |
|
|
|
|
|
|
|
|
elif line.startswith(":23B:"): |
|
|
parsed_data["instruction_code"] = line[5:].strip() |
|
|
|
|
|
|
|
|
elif line.startswith(":32A:"): |
|
|
value = line[5:].strip() |
|
|
if len(value) >= 11: |
|
|
parsed_data["value_date"] = value[:8] |
|
|
parsed_data["currency"] = value[8:11].upper() |
|
|
try: |
|
|
parsed_data["amount"] = float(value[11:].replace(",", ".")) |
|
|
except ValueError: |
|
|
raise ValueError(f"Invalid amount format in :32A: {value[11:]}") |
|
|
|
|
|
|
|
|
elif line.startswith(":50") and ":" in line: |
|
|
tag_end = line.index(":") |
|
|
tag = line[:tag_end+1] |
|
|
content_parts = [line[tag_end+1:].strip()] |
|
|
i += 1 |
|
|
|
|
|
|
|
|
while i < len(lines) and not lines[i].startswith(":"): |
|
|
if lines[i].strip(): |
|
|
content_parts.append(lines[i].strip()) |
|
|
i += 1 |
|
|
i -= 1 |
|
|
|
|
|
full_content = "\n".join(content_parts) |
|
|
parsed_data["ordering_customer"] = full_content |
|
|
|
|
|
|
|
|
iban_match = re.search(r'([A-Z]{2}\d{2}[A-Z0-9\s]{12,34})', full_content) |
|
|
if iban_match: |
|
|
parsed_data["ordering_customer_account"] = iban_match.group(1).replace(" ", "") |
|
|
|
|
|
|
|
|
elif line.startswith(":52A:"): |
|
|
parsed_data["ordering_bank_bic"] = line[5:].strip()[:11] |
|
|
elif line.startswith(":52D:"): |
|
|
parsed_data["ordering_bank_name"] = line[5:].strip() |
|
|
|
|
|
|
|
|
elif line.startswith(":56A:"): |
|
|
parsed_data["intermediary_bank_bic"] = line[5:].strip()[:11] |
|
|
elif line.startswith(":56D:"): |
|
|
parsed_data["intermediary_bank_name"] = line[5:].strip() |
|
|
|
|
|
|
|
|
elif line.startswith(":57A:"): |
|
|
parsed_data["beneficiary_bank_bic"] = line[5:].strip()[:11] |
|
|
elif line.startswith(":57D:"): |
|
|
parsed_data["beneficiary_bank_name"] = line[5:].strip() |
|
|
|
|
|
|
|
|
elif line.startswith(":59"): |
|
|
tag_end = line.index(":") |
|
|
tag = line[:tag_end+1] |
|
|
content_parts = [line[tag_end+1:].strip()] |
|
|
i += 1 |
|
|
|
|
|
|
|
|
while i < len(lines) and not lines[i].startswith(":"): |
|
|
if lines[i].strip(): |
|
|
content_parts.append(lines[i].strip()) |
|
|
i += 1 |
|
|
i -= 1 |
|
|
|
|
|
full_content = "\n".join(content_parts) |
|
|
parsed_data["beneficiary"] = full_content |
|
|
|
|
|
|
|
|
iban_match = re.search(r'([A-Z]{2}\d{2}[A-Z0-9\s]{12,34})', full_content) |
|
|
if iban_match: |
|
|
parsed_data["beneficiary_account"] = iban_match.group(1).replace(" ", "") |
|
|
|
|
|
|
|
|
elif line.startswith(":70:"): |
|
|
content_parts = [line[4:].strip()] |
|
|
i += 1 |
|
|
while i < len(lines) and not lines[i].startswith(":"): |
|
|
if lines[i].strip(): |
|
|
content_parts.append(lines[i].strip()) |
|
|
i += 1 |
|
|
i -= 1 |
|
|
parsed_data["remittance_info"] = "\n".join(content_parts) |
|
|
|
|
|
|
|
|
elif line.startswith(":71A:"): |
|
|
parsed_data["charges"] = line[5:].strip() |
|
|
|
|
|
|
|
|
elif line.startswith(":72:"): |
|
|
content_parts = [line[4:].strip()] |
|
|
i += 1 |
|
|
while i < len(lines) and not lines[i].startswith(":"): |
|
|
if lines[i].strip(): |
|
|
content_parts.append(lines[i].strip()) |
|
|
i += 1 |
|
|
i -= 1 |
|
|
parsed_data["bank_to_bank_info"] = "\n".join(content_parts) |
|
|
|
|
|
i += 1 |
|
|
|
|
|
|
|
|
required_fields = ["value_date", "currency", "amount", "ordering_customer", "beneficiary"] |
|
|
missing = [f for f in required_fields if f not in parsed_data] |
|
|
if missing: |
|
|
raise ValueError(f"Missing required fields: {missing}") |
|
|
|
|
|
return SWIFTExtractedMT103(**parsed_data) |
|
|
|
|
|
|
|
|
async def exemple_generation_swift(): |
|
|
"""Exemple de génération d'un message SWIFT MT103.""" |
|
|
print("📨 Agent SWIFT: Génération de message MT103") |
|
|
print("=" * 60) |
|
|
|
|
|
demande = """ |
|
|
Je veux transférer 15 000 euros de mon compte à la BNP Paribas (BIC: BNPAFRPPXXX) |
|
|
vers le compte de Jean Dupont à la Société Générale (BIC: SOGEFRPPXXX) |
|
|
le 15 décembre 2024. |
|
|
|
|
|
Mon compte: FR76 3000 4000 0100 0000 0000 123 |
|
|
Compte bénéficiaire: FR14 2004 1010 0505 0001 3M02 606 |
|
|
Référence: INVOICE-2024-001 |
|
|
Motif: Paiement facture décembre 2024 |
|
|
Les frais sont à ma charge. |
|
|
""" |
|
|
|
|
|
print(f"Demande:\n{demande}\n") |
|
|
|
|
|
prompt = f""" |
|
|
Génère un message SWIFT MT103 à partir de cette demande: |
|
|
{demande} |
|
|
|
|
|
Fournis les informations structurées suivantes: |
|
|
- BIC émetteur et récepteur |
|
|
- Date de valeur (format YYYYMMDD) |
|
|
- Devise et montant |
|
|
- Données ordonnateur et bénéficiaire |
|
|
- Référence et motif |
|
|
- Qui paie les frais (OUR = ordonnateur, SHA = partagé, BEN = bénéficiaire) |
|
|
""" |
|
|
|
|
|
result = await swift_generator.run(prompt) |
|
|
|
|
|
print("✅ Message SWIFT généré:") |
|
|
print(result.output) |
|
|
print() |
|
|
|
|
|
|
|
|
print("📊 Extraction des données structurées...") |
|
|
|
|
|
|
|
|
swift_lines = [] |
|
|
for line in result.output.split("\n"): |
|
|
if line.strip().startswith(":") and ":" in line: |
|
|
swift_lines.append(line.strip()) |
|
|
|
|
|
if swift_lines: |
|
|
swift_message = "\n".join(swift_lines) |
|
|
print("Message SWIFT extrait:") |
|
|
print(swift_message) |
|
|
print() |
|
|
|
|
|
|
|
|
try: |
|
|
extracted = parse_swift_mt103_advanced(swift_message) |
|
|
print("✅ Données extraites et validées:") |
|
|
print(f" Référence: {extracted.field_20}") |
|
|
print(f" Date: {extracted.field_32A.value_date}") |
|
|
print(f" Montant: {extracted.field_32A.amount:,.2f} {extracted.field_32A.currency}") |
|
|
print(f" Ordonnateur: {extracted.field_50K[:50]}...") |
|
|
print(f" Bénéficiaire: {extracted.field_59[:50]}...") |
|
|
print(f" Frais: {extracted.field_71A}") |
|
|
except Exception as e: |
|
|
print(f"⚠️ Erreur de parsing structuré: {e}") |
|
|
|
|
|
extraction = await swift_parser.run( |
|
|
f"Extrais les données structurées du message SWIFT suivant:\n{swift_message}" |
|
|
) |
|
|
print(extraction.output[:500]) |
|
|
else: |
|
|
|
|
|
extraction = await swift_parser.run( |
|
|
f"Extrais les données structurées du message SWIFT suivant:\n{result.output}" |
|
|
) |
|
|
print(extraction.output[:500]) |
|
|
|
|
|
|
|
|
async def exemple_parsing_swift(): |
|
|
"""Exemple de parsing d'un message SWIFT existant.""" |
|
|
print("\n🔍 Agent SWIFT: Parsing de message MT103") |
|
|
print("=" * 60) |
|
|
|
|
|
swift_message = """ |
|
|
:20:NONREF |
|
|
:23B:CRED |
|
|
:32A:241215EUR15000.00 |
|
|
:50K:/FR76300040000100000000000123 |
|
|
ORDRE DUPONT JEAN |
|
|
RUE DE LA REPUBLIQUE 123 |
|
|
75001 PARIS FRANCE |
|
|
|
|
|
:59:/FR1420041010050500013M02606 |
|
|
BENEFICIAIRE MARTIN PIERRE |
|
|
AVENUE DES CHAMPS ELYSEES 456 |
|
|
75008 PARIS FRANCE |
|
|
|
|
|
:70:Paiement facture décembre 2024 |
|
|
:71A:OUR |
|
|
""" |
|
|
|
|
|
print("Message SWIFT à parser:\n") |
|
|
print(swift_message) |
|
|
print() |
|
|
|
|
|
result = await swift_parser.run( |
|
|
f"Parse ce message SWIFT MT103 et extrais toutes les informations:\n{swift_message}\n\n" |
|
|
"Fournis:\n- Type de message\n- Date de valeur\n- Montant et devise\n" |
|
|
"- Données ordonnateur\n- Données bénéficiaire\n- Référence et motif\n- Frais" |
|
|
) |
|
|
|
|
|
print("✅ Données extraites:") |
|
|
print(result.output) |
|
|
|
|
|
|
|
|
print("\n🔧 Parsing technique avec validation avancée:") |
|
|
try: |
|
|
|
|
|
parsed = parse_swift_mt103_advanced(swift_message) |
|
|
print("✅ Message SWIFT parsé et validé avec succès:") |
|
|
print(f" Référence (:20:): {parsed.field_20}") |
|
|
print(f" Code instruction (:23B:): {parsed.field_23B}") |
|
|
print(f" Date de valeur: {parsed.field_32A.value_date}") |
|
|
print(f" Devise: {parsed.field_32A.currency}") |
|
|
print(f" Montant: {parsed.field_32A.amount:,.2f} {parsed.field_32A.currency}") |
|
|
print(f" Ordonnateur (:50K:):\n {parsed.field_50K.replace(chr(10), chr(10) + ' ')}") |
|
|
if parsed.ordering_customer_account: |
|
|
print(f" → IBAN ordonnateur extrait: {parsed.ordering_customer_account}") |
|
|
if parsed.field_52A: |
|
|
print(f" Banque ordonnateur (:52A:): {parsed.field_52A}") |
|
|
if parsed.field_56A: |
|
|
print(f" Banque intermédiaire (:56A:): {parsed.field_56A}") |
|
|
if parsed.field_57A: |
|
|
print(f" Banque bénéficiaire (:57A:): {parsed.field_57A}") |
|
|
print(f" Bénéficiaire (:59:):\n {parsed.field_59.replace(chr(10), chr(10) + ' ')}") |
|
|
if parsed.beneficiary_account: |
|
|
print(f" → IBAN bénéficiaire extrait: {parsed.beneficiary_account}") |
|
|
if parsed.field_70: |
|
|
print(f" Motif (:70:): {parsed.field_70}") |
|
|
print(f" Frais (:71A:): {parsed.field_71A}") |
|
|
if parsed.field_72: |
|
|
print(f" Info banque (:72:): {parsed.field_72}") |
|
|
except Exception as e: |
|
|
print(f"❌ Erreur lors du parsing: {e}") |
|
|
import traceback |
|
|
traceback.print_exc() |
|
|
|
|
|
|
|
|
async def exemple_synthese_swift(): |
|
|
"""Exemple de synthèse d'un message SWIFT depuis plusieurs sources.""" |
|
|
print("\n🔄 Agent SWIFT: Synthèse de message") |
|
|
print("=" * 60) |
|
|
|
|
|
contexte = """ |
|
|
Informations de la transaction: |
|
|
- Virement international de 50 000 USD |
|
|
- De: ABC Bank New York (BIC: ABCDUS33XXX) vers XYZ Bank Paris (BIC: XYZDFRPPXXX) |
|
|
- Date: 20 janvier 2025 |
|
|
- Compte ordonnateur: US64 SVBKUS6SXXX 123456789 |
|
|
- Compte bénéficiaire: FR76 3000 4000 0100 0000 0000 456 |
|
|
- Référence client: TXN-2025-001 |
|
|
- Motif: Paiement services consultance Q1 2025 |
|
|
- Frais partagés (SHA) |
|
|
""" |
|
|
|
|
|
print(f"Contexte:\n{contexte}\n") |
|
|
|
|
|
result = await swift_generator.run( |
|
|
f"Génère un message SWIFT MT103 complet et correctement formaté:\n{contexte}\n\n" |
|
|
"Assure-toi que:\n- Les BIC sont au bon format\n- La date est au format YYYYMMDD\n" |
|
|
"- Le montant a 2 décimales\n- Les comptes incluent le code pays\n" |
|
|
"- Tous les champs obligatoires sont présents" |
|
|
) |
|
|
|
|
|
print("✅ Message SWIFT synthétisé:") |
|
|
swift_msg = result.output |
|
|
|
|
|
|
|
|
swift_lines = [] |
|
|
for line in swift_msg.split("\n"): |
|
|
if line.strip().startswith(":"): |
|
|
swift_lines.append(line.strip()) |
|
|
|
|
|
if swift_lines: |
|
|
print("\n".join(swift_lines)) |
|
|
else: |
|
|
print(swift_msg) |
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
print("\n" + "=" * 60) |
|
|
print("EXEMPLES D'AGENTS SWIFT AVEC PYDANTICAI") |
|
|
print("=" * 60 + "\n") |
|
|
|
|
|
asyncio.run(exemple_generation_swift()) |
|
|
asyncio.run(exemple_parsing_swift()) |
|
|
asyncio.run(exemple_synthese_swift()) |
|
|
|
|
|
print("\n" + "=" * 60) |
|
|
print("✅ Tous les exemples terminés!") |
|
|
print("=" * 60) |
|
|
|
|
|
|