Comment apprendre l'EAD à un LLM : fine-tuning (3/3)

Disclaimer: la démarche présentée dans ce billet ne constitue pas un exemple complet et abouti de personnalisation d'un LLM. Si le modèle fine-tuné obtenu donne des résultats plutôt satisfaisants, il est largement améliorable, et un "vrai" processus de post-training dans le but d'obtenir un modèle fine-tuné viable en production devrait inclure à minima deux étapes supplémentaires : optimisation des paramètres du fine-tuning, et évaluation de la précision des résultats (le tout avec des outils et stratégies dédiées), ainsi sans doute qu'une amélioration qualitative du dataset d'entraînement.

Alors que le RAG permet d’améliorer la pertinence des réponses d’un modèle en le “connectant” à une base de connaissance externe qui vient alimenter dite son espace de mots avec un corpus spécifique en amont de l’inférence proprement dite, le fine-tuning poursuit le même objectif d’augmentation de la précision des réponses d’un LLM mais de manière différente : il consiste à affiner un modèle pré-entraîné pour le customiser sur des cas d’usage spécifiques en continuant à l’entraîner avec un nouvel ensemble de données ciblées sur la tâche ou le domaine à apprendre, en modifiant pour cela ses paramètres (les poids des neurones du Transformer) Si le RAG ne nécessite pas forcément de s’appuyer sur une grosse infrastructure, le fine-tuning de modèle implique un processus potentiellement long et coûteux en ressources car, même si l’ajustement s’applique sur un modèle déjà pré-entraîné, la modification ou l’adaptation des poids au sein des couches de réseaux de neurones comprenant des milliards de paramètres n’est pas une opération triviale. Par contre, non seulement le fine-tuning augmente significativement les performances d’un modèle de base, mais cette approche peut se révéler très avantageuse ensuite pour l’inférence car un petit modèle fine-tuné peut donner de meilleurs résultats qu’un gros modèle généraliste.


Les discussions sont nombreuses sur le RAG vs le fine-tuning comme scenario approprié d’amélioration de la précision des réponses des LLM, on considère en général que le RAG est plus approprié pour l’intégration de nouvelles bases de connaissances dans le corpus du modèle, tandis que le fine-tuning est plus efficace quand il s’agit de normaliser l’output d’un modèle selon une certaine structure ou d’apprendre au modèle des tâches complexes.


Quel est l'enjeu de l'apprentissage de l'EAD/XML à un LLM par du fine-tuning, alors que quelques requêtes sur les chatbots de GPT, Claude ou encore mieux Deepseeker v3, montrent que les très gros LLM sont en capacité de produire en zero-shot de l'EAD détaillé et conforme à la DTD ? En fait il rejoint celui de l'accès simplifié aux capacités de l'IA générative dans des environnements "LLM desktop" en disposant d'un modèle de petite taille, portable et ne nécessitant pas de GPU pour l'inférence, à faible latence et parfaitement customisé, facilement intégrable avec les outils actuels d'exposition d'endpoints d'inférence, et (ce n'est pas le moins important) parfaitement personnalisable sur le type de résultats attendus (langue du contenu textuel, variante EAD de son choix...).

Généralités

Les techniques mêmes de fine-tuning peuvent être assez subtiles et complexes, et nécessitent une compréhension relativement fine des architectures des modèles afin de bien choisir le modèle initial et de recourir à la bonne stratégie.

Méthodes de fine-tuning

Parmi les choix possibles de méthodologie de fine-tuning, on peut distinguer à gros traits :

  • le Supervised Fine-Tuning (SFT) : le SFT, ou full fine-tuning à base d’instructions, consiste la plupart du temps à transformer un LLM à la base purement génératif en un modèle conversationnel capable de répondre à des questions sur de nouveaux domaines de connaissances ou de réaliser une tâche spécifique, et ce à partir d’un jeu de données composé d’instructions et de réponses. Ce processus au cours duquel tous les paramètres du modèle sont modifiés garantit en général une très bonne adaptation du modèle, mais nécessite un dataset d’entraînement très volumineux et une infrastructure conséquente. En général, les principaux LLM de fondation proposent déjà des versions fine-tunées selon un mode d’instructions/réponses (ce sont en général les modèles suffixés avec “intruct”, comme par exemple HuggingFaceTB/SmolLM2-1.7B-Instruct), et l'on trouve pléthore de datasets constitué à cette fin.

  • le Parameter-Efficient Fine-Tuning (PEFT) : Le fine-tuning par PEFT par contre, en ne se limitant pas aux templates de type instructions, peut être étendu à tout type de tâche et de dataset (données non structurées, tâches de classification… ), et présente l’avantage de réduire les ressources computationnelles requises en ne mettant à jour que les dernières couches de neurones du modèle. En effet, les différentes techniques de PEFT consistent à geler les poids du modèle et à modifier uniquement les dernières couches du réseau de neurones selon plusieurs stratégies : ajout de matrices finetunables dans les couches du réseau transformers (méthode LoRA), combinaison de la méthode LoRA avec un modèle quantifié (méthode QLoRA), ajout de modules dans le modèle (méthode Adapters), etc… Ces techniques de personnalisation plus légères que le SFT et qui ne demandent pas forcément des datasets très volumineux rendent les opérations de fine-tuning réalisables sur les offres gratuites de plateformes “classiques” telles que Kaggle ou Google Colab. D'un point de vue pratique, les fichiers des adaptateurs formés avec PEFT sont également par construction d'un ordre de grandeur plus petit que le modèle complet, les rendant plus pratique à stocker, partager et charger.

  • On peut aussi ajouter à cette liste des méthodes conceptuellement différentes mais en pratique complémentaires relevant du Reinforcement Learning from Human Feedback (RLHF) et qui consistent à aligner le modèle sur des exemples humainement validés (par exemple à partir de datasets d’instructions annotés par une paire de réponses préférée/rejetée).

Choix du modèle

Le choix du modèle initial à fine-tuner dépend fortement de la nature de la tâche à apprendre au modèle : pour une tâche relevant de la génération de texte au sens strict (de l’auto-complétion par exemple) il est plus judicieux d’entraîner un modèle génératif de base (non déjà fine-tuné) sur des raw data de type input/output, tandis que pour des tâches exécutées dans la cadre d’un usage conversationnel il sera plus intéressant d’entraîner un modèle déjà fine-tuné avec de nouvelles instructions qui mobiliseront des types d’usages sur lesquels il est déjà designé (à la nuance près que parfois le modèle déjà fine-tuné aura des difficultés à s’ajuster à de nouvelles instructions, et que selon les cas il reste plus intéressant de partir d’un modèle de base).

Ce choix doit aussi être guidé par le degré de connaissance préalable du modèle du domaine (qui peut être évalué juste avec quelques prompts), sachant que le fine-tuning fonctionnera mieux lorsqu’il s’agit de tirer parti des connaissances déjà présentes dans le modèle de base, qu’à contrario il va être plus long et difficile d’apprendre à un modèle des informations complètement nouvelles.

A noter que la taille minimale du dataset, c’est-à dire le nombre d’instructions nécessaires pour garantir que le modèle s’appuiera bien sur ces nouvelles connaissances pour générer ses outputs, dépend d’un ensemble de paramètres spécifiques à chaque projet (le nombre de paramètres du modèle initial, son niveau de connaissance préalable de la nouvelle tâche ou domaine métier, la complexité de ces derniers…), et peut varier de quelques milliers à plusieurs centaines de milliers. Par contre, afin de garantir un ajustement optimal du modèle, la qualité du jeu de données d'apprentissage est fondamentale, celui-ci devant remplir les meilleurs conditions possibles de complétude et de diversité par rapport aux cas d'usages envisagés.

Cas pratique : fine-tuner un LLM pour la génération d'inventaires encodés en EAD

Constitution du dataset d'entraînement

Comme souligné plus haut, un grand nombre de datasets de tout type sont disponibles et réutilisables sur HuggingFace mais selon l’objectif poursuivi, on peut ne pas trouver de jeu de données pré-existant adéquat, auquel cas il faut le constituer soi-même, cette phase étant en fait l’étape la plus longue et la plus exigeante du processus.

Dans cette hypothèse de création locale de son propre set d'instructions, deux types de solutions complémentaires sont envisageables : soit l’on dispose de données primaires pouvant servir de base fiable à la création d’exemples, auquel cas on peut alors scripter l’extraction de paires prompt/completion à partir de ces données réelles, soit, sans données de terrain, une solution désormais standard consiste à utiliser un LLM afin de lui faire générer à partir d'un prompt un jeu de données dites de ce fait “synthétiques”. Cette méthode peut paraitre surprenante mais est en fait maintenant très répandue, et se double de méthodologies diverses (elles aussi basées sur des LLM) permettant d'évaluer et de garantir la qualité et la vraisemblance des données synthétiques.ainsi obtenues.

Dans ce cas, le prompt à fournir au LLM doit être le plus précis et complet possible autant sur la méthode de création des instructions que leur structuration en sortie :

Voir par exemple ce prompt demandant à un LLM de générer quatre types d’instructions structurées en Json à partir d’un template EAD minimaliste

You are an expert XML and EAD metadata assistant. Your task is to generate diverse instruction-completion pairs for fine-tuning a model to work with EAD/XML files. 

### Input:
Here is an example EAD/XML file:
<ead>
    <archdesc level="fonds">
        <did>
            <repository>
                <corpname>EPFL Bibliothèque</corpname>
            </repository>
            <unittitle>Fonds Martin Vetterli</unittitle>
            <unitdate normal="2023">2023</unitdate>
        </did>
        <dsc>
            <c level="series">
                <did>
                    <unittitle>serie1</unittitle>
                </did>
            </c>
            <c level="series">
                <did>
                    <unittitle>serie2</unittitle>
                </did>
            </c>
        </dsc>
    </archdesc>
</ead>

### Task:
Generate 4 types of instruction-completion pairs based on this EAD/XML file:

1. **Open-Ended Prompt**:
   - Create a natural-language instruction based on the content of the file. For example, instruct the model to generate a complete EAD/XML entry based on archival metadata like the title, repository, and components.
   - Provide the full and well-formed XML as the completion.

2. **Template-Based Prompt**:
   - Create a prompt asking the model to generate an XML template for a specific element (e.g., `<archdesc>` or `<dsc>`). 
   - The completion should include the structure of the XML element with placeholders for attributes and text values.

3. **Partial XML Prompt**:
   - Provide an incomplete XML snippet (e.g., the beginning of an `<archdesc>` element) and ask the model to complete it.
   - The completion should add the missing parts of the XML based on the input.

4. **Instruction with Schema Emphasis**:
   - Write a schema-specific prompt, such as asking the model to generate a specific XML sub-element (e.g., `<controlaccess>` or `<scopecontent>`).
   - The completion should provide the corresponding XML content using realistic values.

### Output Format:
Return a JSON object with the following structure:
[
    {
        "type": "Open-Ended Prompt",
        "prompt": "Write the prompt here...",
        "completion": "Write the completion here..."
    },
    {
        "type": "Template-Based Prompt",
        "prompt": "Write the prompt here...",
        "completion": "Write the completion here..."
    },
    {
        "type": "Partial XML Prompt",
        "prompt": "Write the prompt here...",
        "completion": "Write the completion here..."
    },
    {
        "type": "Instruction with Schema Emphasis",
        "prompt": "Write the prompt here...",
        "completion": "Write the completion here..."
    }
]

Pour notre use case, on choisit une méthode hybride combinant les deux approches données réelles/données synthétiques afin d’optimiser à la fois le volume et la variété du jeu de données d’entraînement, et déclinée en trois étapes aboutissant chacune à la création d’un sous-ensemble spécifique d’instructions.

  1. Les données réelles sont issues des inventaires qualifiés et formalisés en EAD/XML du Catalogue général des manuscrits (CGM) mis à disposition par la BnF via un dump : la stratégie consiste à sélectionner un échantillon d’une cinquantaine d’inventaires parmi les 1800 fichiers, puis pour chacun d’entre eux à les segmenter en sections xml selon différents niveaux de granularité (au niveau le plus fin de l’élément xml simple ou plus agrégé de l’élément englobant) afin d’obtenir des portions xml significatives à la fois de la signification de chaque balise et de la structure arborescente des composants entre eux. Sur cette base, on intègre alors de manière itérative chacun des extraits EAD dans un prompt ensuite envoyé au modèle gpt-4o-mini avec comme commande qu'il génère une requête ayant pu donner comme résultat l’extrait EAD en question. On s'assure de cette manière que le LLM se basera bien sur des exemples réels, conformes, et suffisamment complets pour que les instructions créées reflètent bien la structuration hiérarchique du XML et la sémantique du contenu EAD. Voici le prompt système utilisé
You are an expert XML and EAD metadata assistant.
Your task is to do reverse question-answering from an EAD/XML completion content to enhance the quality of instruction-completion pairs for fine-tuning a model to work with EAD/XML files.

### Input:
You will be given an EAD/XML element. Analyze the structure and content, and focus on this tasks:

1. **Create a user query that could have this content as a result**:
   - Be very specific in the query
   - Include attributes values if the resulting XML content has attributes

### Output Format:
For each XML tag, return the prompt you generate as a string

### Example
Input XML:
<bibliography><p><bibref linktype="simple">Nicolas Barbey et Agnès Verret, "Mauriac", dans Trésors de la bibliothèque de Bordeaux, Le Festin, 2014, p. 76-81</bibref></p></bibliography>

String Output:
Generate a valid and compliant <bibliography> element including this reference : Nicolas Barbey et Agnès Verret, "Mauriac", dans Trésors de la bibliothèque de Bordeaux, Le Festin, 2014, p. 76-81.

et avec cet extrait EAD basique

<c id="PA1010407" level="item"><controlaccess><persname>Brazier (Nicolas)</persname></controlaccess></c>

gpt-4o-mini génère le prompt suivant

Generate a valid and compliant <c> element with the id attribute set to "PA1010407" and level attribute set to "item", including a <controlaccess> section that contains the personal name "Brazier (Nicolas)
  1. Le deuxième sous-ensemble de données purement synthétiques (obtenu avec gpt-3.5-turbo) est le résultat d’une combinaison de templates de prompt croisant aléatoirement des valeurs possibles de balises EAD/XML avec des schémas de structuration. Par exemple pour un élément <unittitle>, on fournit les contenus possibles
"unittitle": [
                "Correspondance de Marcel Proust (1871-1922)",
                "Archives du cabinet de Georges Clemenceau",
                "Documents du procès Dreyfus",
                "Collection des affiches de Mai 68",
                "Fonds du journal Le Monde (1944-2000)",
                "Archives de la Comédie-Française",
                "Documents de la construction du métro parisien",
                "Collection des manuscrits de Victor Hugo",
                "Archives de l'École polytechnique",
                "Fonds des architectes du château de Versailles"
            ],

combinés avec ce panel de templates de prompt

content_templates = [
            "Create an EAD/XML element for {element_name} with the following content: {content}",
            "How do I properly format a {element_name} tag in EAD/XML?",
            "Convert this information into an EAD {element_name} element: {content}",
            "Write the EAD/XML for a {element_name} describing: {content}",
            "Format this content as an EAD/XML {element_name} element: {content}",
            "Encode the following {element_name} information in EAD/XML: {content}",
            "Structure this {element_name} content in valid EAD/XML: {content}",
            "Create an EAD-compliant {element_name} element for: {content}",
            "Format the following {element_name} details in EAD/XML: {content}",
            "Generate EAD/XML markup for this {element_name}: {content}"
        ]

assemblés via ce prompt système

You are an expert in EAD/XML encoding.
Provide concise, valid EAD/XML markup as responses.
Include only the necessary XML elements without explanation.
Ensure proper nesting and valid syntax.
Text content should be in French but XML tags and attributes in English.

Ce qui génère des paires de prompt-completion du type

Prompt: Write the EAD/XML for a famname describing: Famille de Montmorency

Completion: <famname> 
    <name>Famille de Montmorency</name>
</famname>

Pour un élément englobant <eadheader>, on y ajoute ce template json

"eadheader": {"children": ["eadid", "filedesc", "profiledesc", "revisiondesc"]},

que l’on associe à d’autres types de prompts

container_templates = [
            "Create an EAD/XML {element_name} element with its required child elements. Include: {children}",
            "Show the structure of a {element_name} element containing {children}",
            "Generate a complete {element_name} section with the following components: {children}",
            "What's the proper nesting structure for a {element_name} element with {children}?",
            "Format a {element_name} container with these nested elements: {children}",
            "Create a hierarchical {element_name} structure incorporating {children}",
            "Demonstrate the correct nesting of {children} within a {element_name} element",
            "Structure a complex {element_name} element containing {children}",
            "Build an EAD/XML {element_name} hierarchy with {children}",
            "Show the organization of {children} inside a {element_name} container"
        ]

Ce qui donne par exemple

Prompt: Demonstrate the correct nesting of eadid, filedesc, profiledesc, revisiondesc within a eadheader element

Completion: <eadheader>
    <eadid>Identifier of the EAD</eadid>
    <filedesc>
        <titlestmt>
            <title>Title of the EAD</title>
        </titlestmt>
        <publicationstmt>
            <publisher>Name of the publisher</publisher>
            <date>Date of publication</date>
        </publicationstmt>
        <sourcedesc>
            <p>Information about the source of the EAD</p>
        </sourcedesc>
    </filedesc>
    <profiledesc>
        <creation>Date of creation</creation>
        <langusage>Language(s) used in the EAD</langusage>
    </profiledesc>
    <revisiondesc>
        <change>Date of last revision</change>
        <item>Details of the revision</item>
    </revisiondesc>
</eadheader>
  1. Le troisième sous-ensemble enfin reprend la logique du précédent en combinant d’autres exemples plus axés sur la création d’éléments de structure parents-enfants, afin d'obtenir ce type d'instruction :
Prompt: Build a nested component structure using 2 levels of description

Completion: <ead>
  <archdesc level="collection">
    <did>
      <unittitle>Archives de la famille Dupont</unittitle>
      <unitid>FR-12345</unitid>
      <unitdate normal="1900/2000">20th century</unitdate>
    </did>
    <scopecontent>
      <p>Cette collection contient des documents relatifs à la famille Dupont.</p>
    </scopecontent>
    <dsc>
      <c level="series">
        <did>
          <unittitle>Série 1: Correspondance</unittitle>
          <unitid>FR-12345-1</unitid>
        </did>
        <scopecontent>
          <p>Cette série contient la correspondance de la famille Dupont.</p>
        </scopecontent>
        <c level="subseries">
          <did>
            <unittitle>Sous-série 1.1: Correspondance interne</unittitle>
            <unitid>FR-12345-1.1</unitid>
          </did>
          <scopecontent>
            <p>Cette sous-série contient la correspondance interne de la famille Dupont.</p>
          </scopecontent>
        </c>
      </c>
    </dsc>
  </archdesc>
</ead>

Au final, au terme de ces trois process et après quelques opérations de dédoublonnage et de ré-équilibrage de la représentativité des balises EAD afin d’éviter des biais d’apprentissage, on obtient un dataset de 38 000 instructions déposé sur HuggingFace : Geraldine/Ead-Instruct-38k

enter image description here

Le code complet est accessible dans ce notebook sur Kaggle

Etapes du fine-tuning


Pour une explication détaillée du paramétrage de l'apprentissage par la méthode LoRA, voir par exemple https://magazine.sebastianraschka.com/p/practical-tips-for-finetuning-llms


Paradoxalement, la phase de fine-tuning en elle-même est bien plus simple que la création du dataset d'entraînement.

  • Choix du modèle à fine-tuner : on choisit le modèle de Meta llama-3.2-3b-instruct, une variante déjà fine-tunée de llama-3.2-3b selon les méthodes SFT et RHEL, et disponible ici : meta-llama/Llama-3.2-3B-Instruct.

  • Le fine-tuning en lui-même est réalisé avec les librairies transformers et peft selon la méthode QLoRA (le modèle de base llama-3.2-3b-Instruct est téléchargé en version 4-bit). La phase d'apprentissage avec des itérations sur trois epochs a duré environ trois heures sur un GPU A100 et a été monitorée avec la plateforme wandb.

enter image description here

enter image description here

Le code est lui aussi accessible sur cet autre notebook Kaggle.

Résultats

Au-delà de la définition et de la mesure de la fonction de perte ("loss") durant le post-training du modèle, qui quantifie l’écart entre les résultats prévus et les objectifs réels, les performances et les capacités de généralisation du modèle fine-tuné doivent ensuite être évaluées par la mise en oeuvre de métriques d'évaluation spécifiques. Sur des tâches linguistiques de génération de texte, les mesures de Machine Learning classiques (exactitude, la précision, le rappel, score F1) laissent place à des mesures spécialisées pour la langage naturel telles que ROUGE ou BLEU. Quoi qu'il en soit, l'évaluation des LLM et plus largement l'audit des systèmes d'IA est un sujet en soi, et on peut se reporter à cette note réalisée pour la CNIL et disponible sur HAL pour une étude globale des techniques d'audits, benchmarks et autres leaderboards.

Pas d'évaluation en bonne et due forme dans cet exemple de fine-tuning, mais ci-dessous quelques exemples d'outputs du nouveau modèle, montrant que celui-ci a plutôt bien appris les divers aspects de l'EAD souhaité selon les examples fournis dans le dataset d'entraînement (contenus en français même avec des prompts en anglais), produit une structuration et une imbrication des composants conforme, et est capable de se généraliser sur des types de contenus inconnus à priori. Par contre on remarque qu'il tend à "oublier" d'intégrer le header dans la description, ou à faire des erreurs de balises enfants quand il l'intègre, ou encore à créer des arborescences de composants trop profondes, tout ceci révélant une marge de progression qualitative dans les données d'entraînement.

Exemple 1

Prompt
Generate a complete EAD template for a correspondence archive between Henri Bosco and Jean Caminade.
The collection contains two series of letters from two periods: 1965-1966 and 1968-1970. 
Don't forget the eadheader section.

Réponse
<ead xmlns="urn:isbn:1-931666-22-9" xmlns:xlink="http://www.w3.org/1999/xlink">
  <eadheader>
    <eadid>example-ead</eadid>
    <filedesc>
      <titlestmt>
        <title>Archives de la correspondance entre Henri Bosco et Jean Caminade</title>
      </titlestmt>
      <publicationstmt>
        <publisher>Example Publisher</publisher>
        <date>2022</date>
      </publicationstmt>
      <profiledesc>
        <creation>Encoded by an expert</creation>
        <langusage>French</langusage>
      </profiledesc>
    </filedesc>
  </eadheader>
  <archdesc level="collection">
    <did>
      <unittitle>Fonds de la correspondance entre Henri Bosco et Jean Caminade</unittitle>
      <unitid>example-collection</unitid>
      <repository>
        <corpname>Example Repository</corpname>
      </repository>
      <origination>
        <persname>Henri Bosco</persname>
        <persname>Jean Caminade</persname>
      </origination>
    </did>
    <scopecontent>
      <p>Cette collection contient la correspondance entre Henri Bosco et Jean Caminade, regroupée en deux séries de lettres, une de 1965 à 1966 et une autre de 1968 à 1970.</p>
    </scopecontent>
    <dsc>
      <c01 level="series">
        <did>
          <unittitle>Série 1: 1965-1966</unittitle>
        </did>
        <c02 level="subseries">
          <did>
            <unittitle>Sous-série A: Lettres de Henri Bosco</unittitle>
          </did>
          <c03 level="file">
            <did>
              <unittitle>Dossier 1: Lettres de Henri Bosco à Jean Caminade</unittitle>
            </did>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>Dossier 2: Lettres de Jean Caminade à Henri Bosco</unittitle>
            </did>
          </c03>
        </c02>
      </c01>
      <c01 level="series">
        <did>
          <unittitle>Série 2: 1968-1970</unittitle>
        </did>
        <c02 level="subseries">
          <did>
            <unittitle>Sous-série B: Lettres de Jean Caminade</unittitle>
          </did>
          <c03 level="file">
            <did>
              <unittitle>Dossier 1: Lettres de Jean Caminade à Henri Bosco</unittitle>
            </did>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>Dossier 2: Lettres de Henri Bosco à Jean Caminade</unittitle>
            </did>
          </c03>
        </c02>
      </c01>
    </dsc>
  </archdesc>
</ead>

Exemple 2

Prompt
Generate a complete EAD template for a collection of manuscripts by Marguerite Yourcenar, spanning 1951 to 1983. 
The collection includes personal diaries, drafts of published novels, and correspondence with publishers.
Include appropriate <eadheader>, <archdesc>, and series descriptions.

Réponse
<ead xmlns="urn:isbn:1-931666-22-9" xmlns:xlink="http://www.w3.org/1999/xlink">
  <archdesc>
    <did>
      <repository>
        <corpname>Archives Marguerite Yourcenar</corpname>
      </repository>
      <unittitle>Manuscrits de Marguerite Yourcenar</unittitle>
      <unitid>MS-001</unitid>
      <unitdate>1951-1983</unitdate>
    </did>
    <dsc>
      <c01 level="series">
        <did>
          <unittitle>Diaires personnels</unittitle>
        </did>
        <scopecontent>
          <p>Cette série contient des diaires personnels de Marguerite Yourcenar, couvrant la période de 1951 à 1983.</p>
        </scopecontent>
        <c02 level="subseries">
          <did>
            <unittitle>1951-1960</unittitle>
          </did>
          <scopecontent>
            <p>Cette sous-série regroupe les journaux intimes de Marguerite Yourcenar, couvrant la période de 1951 à 1960.</p>
          </scopecontent>
          <c03 level="file">
            <did>
              <unittitle>1951-1952</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient les premiers journaux intimes de Marguerite Yourcenar, écrits entre 1951 et 1952.</p>
            </scopecontent>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>1953-1954</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier regroupe les journaux intimes de Marguerite Yourcenar, écrits en 1953 et 1954.</p>
            </scopecontent>
          </c03>
        </c02>
        <c02 level="subseries">
          <did>
            <unittitle>1961-1970</unittitle>
          </did>
          <scopecontent>
            <p>Cette sous-série contient les journaux intimes de Marguerite Yourcenar, couvrant la période de 1961 à 1970.</p>
          </scopecontent>
          <c03 level="file">
            <did>
              <unittitle>1961-1962</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier regroupe les premiers journaux intimes de Marguerite Yourcenar, écrits en 1961 et 1962.</p>
            </scopecontent>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>1963-1964</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient les journaux intimes de Marguerite Yourcenar, écrits en 1963 et 1964.</p>
            </scopecontent>
          </c03>
        </c02>
      </c01>
      <c01 level="series">
        <did>
          <unittitle>Drafts de romans</unittitle>
        </did>
        <scopecontent>
          <p>Cette série contient des brouillons de romans de Marguerite Yourcenar.</p>
        </scopecontent>
        <c02 level="subseries">
          <did>
            <unittitle>Roman I</unittitle>
          </did>
          <scopecontent>
            <p>Cette sous-série regroupe les brouillons du premier roman de Marguerite Yourcenar.</p>
          </scopecontent>
          <c03 level="file">
            <did>
              <unittitle>Chapter 1</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient le premier chapitre du roman de Marguerite Yourcenar.</p>
            </scopecontent>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>Chapter 2</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient le deuxième chapitre du roman de Marguerite Yourcenar.</p>
            </scopecontent>
          </c03>
        </c02>
        <c02 level="subseries">
          <did>
            <unittitle>Roman II</unittitle>
          </did>
          <scopecontent>
            <p>Cette sous-série regroupe les brouillons du deuxième roman de Marguerite Yourcenar.</p>
          </scopecontent>
          <c03 level="file">
            <did>
              <unittitle>Chapter 1</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient le premier chapitre du roman de Marguerite Yourcenar.</p>
            </scopecontent>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>Chapter 2</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient le deuxième chapitre du roman de Marguerite Yourcenar.</p>
            </scopecontent>
          </c03>
        </c02>
      </c01>
      <c01 level="series">
        <did>
          <unittitle>Correspondance</unittitle>
        </did>
        <scopecontent>
          <p>Cette série contient la correspondance de Marguerite Yourcenar avec des éditeurs et des critiques littéraires.</p>
        </scopecontent>
        <c02 level="subseries">
          <did>
            <unittitle>Correspondance avec éditeurs</unittitle>
          </did>
          <scopecontent>
            <p>Cette sous-série regroupe la correspondance de Marguerite Yourcenar avec des éditeurs pour la publication de ses œuvres.</p>
          </scopecontent>
          <c03 level="file">
            <did>
              <unittitle>Correspondance avec Gallimard</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient la correspondance entre Marguerite Yourcenar et Gallimard pour la publication de son roman.</p>
            </scopecontent>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>Correspondance avec Fayard</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient la correspondance entre Marguerite Yourcenar et Fayard pour la publication de son roman.</p>
            </scopecontent>
          </c03>
        </c02>
        <c02 level="subseries">
          <did>
            <unittitle>Correspondance avec critiques</unittitle>
          </did>
          <scopecontent>
            <p>Cette sous-série regroupe la correspondance de Marguerite Yourcenar avec des critiques littéraires pour la critique de son œuvre.</p>
          </scopecontent>
          <c03 level="file">
            <did>
              <unittitle>Correspondance avec Roger Peyrefitte</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient la correspondance entre Marguerite Yourcenar et Roger Peyrefitte pour la critique de son roman.</p>
            </scopecontent>
          </c03>
          <c03 level="file">
            <did>
              <unittitle>Correspondance avec François Mauriac</unittitle>
            </did>
            <scopecontent>
              <p>Ce dossier contient la correspondance entre Marguerite Yourcenar et François Mauriac pour la critique de son œuvre.</p>
            </scopecontent>
          </c03>
        </c02>
      </c01>
    </dsc>
  </archdesc>
</ead>

Exemple 3

Prompt
Generate a complete EAD template for a family archive of the Dupont family (1800-1950), consisting of legal documents, birth certificates, and handwritten recipes. 
The collection is divided into three series, and the finding aid should include an extensive <scopecontent> section.

Réponse
<ead xmlns="urn:isbn:1-931666-22-9" xmlns:xlink="http://www.w3.org/1999/xlink">
  <eadheader>
    <eadid>FR-123456789-DF</eadid>
    <filedesc>
      <titlestmt>
        <title>Archives of the Dupont family (1800-1950)</title>
      </titlestmt>
      <publicationstmt>
        <publisher>Archives department</publisher>
        <date>2022</date>
      </publicationstmt>
    </filedesc>
  </eadheader>
  <archdesc>
    <did>
      <unittitle>Fonds de la famille Dupont</unittitle>
      <unitid>FR-123456789-DF</unitid>
      <unitdate>1800-1950</unitdate>
      <physdesc>10 boxes</physdesc>
    </did>
    <dsc>
      <c01 level="series">
        <did>
          <unittitle>Série 1: Documents juridiques</unittitle>
          <unitid>FR-123456789-DF-1</unitid>
        </did>
        <c02 level="subseries">
          <did>
            <unittitle>Sous-série 1.1: Contrats</unittitle>
            <unitid>FR-123456789-DF-1.1</unitid>
          </did>
          <c03 level="file">
            <did>
              <unittitle>Dossier 1: Contrats de mariage</unittitle>
              <unitid>FR-123456789-DF-1.1.1</unitid>
            </did>
            <scopecontent>
              <p>Ce dossier contient des contrats de mariage de la famille Dupont.</p>
            </scopecontent>
          </c03>
        </c02>
      </c01>
      <c01 level="series">
        <did>
          <unittitle>Série 2: Documents d'état-civil</unittitle>
          <unitid>FR-123456789-DF-2</unitid>
        </did>
        <c02 level="file">
          <did>
            <unittitle>Dossier 1: Actes de naissance</unittitle>
            <unitid>FR-123456789-DF-2.1</unitid>
          </did>
          <scopecontent>
            <p>Ce dossier contient des actes de naissance des membres de la famille Dupont.</p>
          </scopecontent>
        </c02>
        <c02 level="file">
          <did>
            <unittitle>Dossier 2: Certificats de mariage</unittitle>
            <unitid>FR-123456789-DF-2.2</unitid>
          </did>
          <scopecontent>
            <p>Ce dossier contient des certificats de mariage de la famille Dupont.</p>
          </scopecontent>
        </c02>
      </c01>
      <c01 level="series">
        <did>
          <unittitle>Série 3: Recettes de cuisine</unittitle>
          <unitid>FR-123456789-DF-3</unitid>
        </did>
        <c02 level="file">
          <did>
            <unittitle>Dossier 1: Recettes de cuisine</unittitle>
            <unitid>FR-123456789-DF-3.1</unitid>
          </did>
          <scopecontent>
            <p>Ce dossier contient des recettes de cuisine préparées par la famille Dupont.</p>
          </scopecontent>
        </c02>
      </c01>
    </dsc>
  </archdesc>
</ead>

Comment utiliser le modèle fine-tuné ? (procédures d'installation en local)

Avec la librairie transformers

C’est le moyen standard de téléchargement et de requêtage en local d’un modèle hébergé sur HuggingFace. Ici le Llama-3.2-3b fine-tuné pour la production d’inventaires en EAD peut être downloadé :

  • depuis le dépôt du modèle complet (exemple pour de l’inférence sur GPU)
# exemple pour de l’inférence sur GPU

from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

model = "Geraldine/FineLlama-3.2-3B-Instruct-ead"
device = "cuda" # for GPU usage or "cpu" for CPU usage

tokenizer = AutoTokenizer.from_pretrained(model)
model = AutoModelForCausalLM.from_pretrained(model, quantization_config=bnb_config).to(device)

messages = [
    {"role": "system", "content": "You are an expert in the domain of archival description in the standardized Encoded Archival Description EAD format and intelligent EAD/XML generator."},
    {"role": "user", "content": "I need a <eadheader>"}]

inputs = tokenizer.apply_chat_template(
    messages,
    tokenize = True,
    add_generation_prompt = True,
    return_dict=True,
    return_tensors = "pt",
).to("cuda")

outputs = model.generate(
    **inputs, 
    max_new_tokens = 4096,
    pad_token_id=tokenizer.eos_token_id,
    use_cache = True,)

print(tokenizer.decode(outputs[0], skip_special_tokens=True))
  • ou depuis celui des adaptateurs LoRA (nécessite d’importer la librairie peft)
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig
import torch

bnb_config = BitsAndBytesConfig(
    load_in_4bit=True,
    bnb_4bit_use_double_quant=True,
    bnb_4bit_quant_type="nf4",
    bnb_4bit_compute_dtype=torch.bfloat16
)

peft_model_id = "Geraldine/qlora-FineLlama-3.2-3B-Instruct-ead"
model = AutoModelForCausalLM.from_pretrained(peft_model_id, quantization_config=bnb_config).to(device)
  • ou dans une version compressée plus légère depuis le dépôt des fichiers quantifiés (pour une inférence sur CPU)
from transformers import AutoTokenizer, AutoModelForCausalLM

model_id = "Geraldine/FineLlama-3.2-3B-Instruct-ead-GGUF"
filename = "FineLlama-3.2-3B-Instruct-ead-Q4_K_M.gguf"

tokenizer = AutoTokenizer.from_pretrained(model_id, gguf_file=filename)
model = AutoModelForCausalLM.from_pretrained(model_id, gguf_file=filename)

Avec Ollama

Ollama s’est imposé comme l’outil multi-plateforme le plus simple et pratique pour rendre des LLMs actionnables en local sur des laptops grand public. Il est développé en Go sur llama.cpp, avec un backend pour le téléchargement de modèles compressés ensuite accessibles via une CLI, des clients Python et JS, ainsi qu’un serveur d’API OpenAI-like (voir aussi cet autre billet).

Ollama supportant des modèles quantifiés, l’intégration avec Ollama est proposée depuis la carte du dépôt des différentes versions .gguf du modèle

enter image description here enter image description here

Le modèle est ainsi installé localement enter image description here

avec des endpoints déployés localement enter image description here

Exemples d'application

  • ce chatbot d'inférence comparative, notamment sur le nouveau modèle FineLlama-3.2-3B-Instruct-ead

enter image description here

  • cet éditeur EAD/XML minimaliste automatisant la création d'inventaires en EAD via l'inférence sur FineLlama-3.2-3B-Instruct-ead.

enter image description here

Conclusion

S’il est clair que les petits modèles spécialisés sur des tâches et des domaines de compétences bien précis représentent un des principaux potentiels d’évolution et de croissance de l’IA (largement porté par la dynamique des modèles et outils disponibles en open source), être en capacité de les sur-entraîner ou de les produire est sans aucun doute la clé de l’appropriation en profondeur de l’IA par les communautés professionnelles (à commencer par la nôtre) afin de bénéficier de modèles sur-mesure réellement adaptés aux besoins et aux données, capables de respecter les éventuelles exigences de sécurité et confidentialité par des déploiements locaux, et facilement intégrables dans les SI des établissements.

"> ');