Outil de recherche de fichiers pour Azure OpenAI Assistant (Aperçu) (Version classique)

S’applique uniquement à :le portail classique Foundry. Cet article n’est pas disponible pour le nouveau portail Foundry. En savoir plus sur le nouveau portail.

Note

Les liens de cet article peuvent ouvrir du contenu dans la nouvelle documentation Microsoft Foundry au lieu de la documentation Foundry (classique) que vous affichez maintenant.

Note

L’API des assistants est obsolète et sera retirée le 26 août 2026. Utilisez le service Microsoft Foundry Agents, généralement disponible. Suivez le guide de migration pour mettre à jour vos charges de travail. En savoir plus.

La recherche de fichiers augmente l’Assistant avec des connaissances provenant de l’extérieur de son modèle, telles que les informations sur les produits propriétaires ou les documents fournis par vos utilisateurs. OpenAI analyse et segmente automatiquement vos documents, crée et stocke les incorporations, et utilise la recherche de vecteurs et de mots clés pour récupérer du contenu pertinent pour répondre aux requêtes utilisateur.

Important

  • La recherche de fichiers entraîne des frais supplémentaires au-delà des frais basés sur les jetons pour l’utilisation d’OpenAI Azure.

Prise en charge de la recherche de fichiers

Régions prises en charge

La recherche de fichiers est disponible dans les régions qui prennent en charge les Assistants.

Version de l’API

  • À partir du 01-05-2024-preview

Types de fichiers pris en charge

Note

Pour les types texte/MIME, l’encodage doit être utf-8, utf-16 ou ASCII.

Format de fichier MIME Type
.c text/x-c
.cs text/x-csharp
.cpp text/x-c++
.doc application/msword
.docx application/vnd.openxmlformats-officedocument.wordprocessingml.document
.html text/html
.java text/x-java
.json application/json
.md text/markdown
.pdf application/pdf
.php text/x-php
.pptx application/vnd.openxmlformats-officedocument.presentationml.presentation
.Py text/x-python
.Py text/x-script.python
.rb text/x-ruby
.tex text/x-tex
.txt texte/brut
.css text/css
.js text/javascript
.sh application/x-sh
.ts application/typescript
from openai import AzureOpenAI
    
client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
    api_version="2024-05-01-preview",
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
    )

assistant = client.beta.assistants.create(
  name="Financial Analyst Assistant",
  instructions="You are an expert financial analyst. Use your knowledge base to answer questions about audited financial statements.",
  model="gpt-4-turbo",
  tools=[{"type": "file_search"}],
)

Pour accéder à vos fichiers, l’outil de recherche de fichiers utilise l’objet de magasin de vecteurs. Chargez vos fichiers et créez un magasin de vecteurs pour les contenir. Une fois le magasin vectoriel créé, vous devez interroger son état jusqu’à ce que tous les fichiers soient hors de l’état in_progress pour vous assurer que tout le contenu a terminé le traitement. Le Kit de développement logiciel (SDK) fournit des assistants pour le téléchargement et l'interrogation.

from openai import AzureOpenAI
    
client = AzureOpenAI(
    api_key=os.getenv("AZURE_OPENAI_API_KEY"),  
    api_version="2024-05-01-preview",
    azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
    )

# Create a vector store called "Financial Statements"
vector_store = client.beta.vector_stores.create(name="Financial Statements")
 
# Ready the files for upload to OpenAI
file_paths = ["mydirectory/myfile1.pdf", "mydirectory/myfile2.txt"]
file_streams = [open(path, "rb") for path in file_paths]
 
# Use the upload and poll SDK helper to upload the files, add them to the vector store,
# and poll the status of the file batch for completion.
file_batch = client.beta.vector_stores.file_batches.upload_and_poll(
  vector_store_id=vector_store.id, files=file_streams
)
 
# You can print the status and the file counts of the batch to see the result of this operation.
print(file_batch.status)
print(file_batch.file_counts)

Mettre à jour l’Assistant pour utiliser le nouveau magasin vectoriel

Pour rendre les fichiers accessibles à votre assistant, mettez à jour le tool_resources de l’assistant avec le nouvel identifiant vector_store.

assistant = client.beta.assistants.update(
  assistant_id=assistant.id,
  tool_resources={"file_search": {"vector_store_ids": [vector_store.id]}},
)

Créer un thread

Vous pouvez également joindre des fichiers en tant que pièces jointes de message sur votre thread. Cela crée un autre vector_store associé au thread ou, s’il existe déjà un magasin de vecteurs attaché à ce thread, attachez les nouveaux fichiers au magasin de vecteurs de thread existant. Lorsque vous créez une tâche dans ce thread, l'outil de recherche de fichiers interrogera à la fois le vector_store de votre assistant et le vector_store du thread.

# Upload the user provided file to OpenAI
message_file = client.files.create(
  file=open("mydirectory/myfile.pdf", "rb"), purpose="assistants"
)
 
# Create a thread and attach the file to the message
thread = client.beta.threads.create(
  messages=[
    {
      "role": "user",
      "content": "How many company shares were outstanding last quarter?",
      # Attach the new file to the message.
      "attachments": [
        { "file_id": message_file.id, "tools": [{"type": "file_search"}] }
      ],
    }
  ]
)
 
# The thread now has a vector store with that file in its tool resources.
print(thread.tool_resources.file_search)

Les stockages de vecteurs sont créés à l'aide des pièces jointes de message qui ont une politique d'expiration par défaut de sept jours après leur dernière activité (définie comme la dernière fois que le stockage de vecteurs était inclus dans un processus). Cette valeur par défaut vous permet de gérer vos coûts de stockage vectoriel. Vous pouvez outrepasser ces stratégies d’expiration à tout moment.

Créer une exécution et vérifier la sortie

Créez une exécution et observez que le modèle utilise l’outil de recherche de fichiers pour fournir une réponse à la question de l’utilisateur.

from typing_extensions import override
from openai import AssistantEventHandler, OpenAI
 
client = OpenAI()
 
class EventHandler(AssistantEventHandler):
    @override
    def on_text_created(self, text) -> None:
        print(f"\nassistant > ", end="", flush=True)

    @override
    def on_tool_call_created(self, tool_call):
        print(f"\nassistant > {tool_call.type}\n", flush=True)

    @override
    def on_message_done(self, message) -> None:
        # print a citation to the file searched
        message_content = message.content[0].text
        annotations = message_content.annotations
        citations = []
        for index, annotation in enumerate(annotations):
            message_content.value = message_content.value.replace(
                annotation.text, f"[{index}]"
            )
            if file_citation := getattr(annotation, "file_citation", None):
                cited_file = client.files.retrieve(file_citation.file_id)
                citations.append(f"[{index}] {cited_file.filename}")

        print(message_content.value)
        print("\n".join(citations))

# Then, we use the stream SDK helper
# with the EventHandler class to create the Run
# and stream the response.

with client.beta.threads.runs.stream(
    thread_id=thread.id,
    assistant_id=assistant.id,
    instructions="Please address the user as Jane Doe. The user has a premium account.",
    event_handler=EventHandler(),
) as stream:
    stream.until_done()

Fonctionnement

L'outil de recherche de fichiers implémente plusieurs bonnes pratiques de récupération dès le départ pour vous aider à extraire les données appropriées de vos fichiers et à améliorer les réponses du modèle. L’outil file_search :

  • Réécrit les requêtes utilisateur pour les optimiser pour la recherche.
  • Décompose les requêtes utilisateur complexes en plusieurs recherches qu’elle peut exécuter en parallèle.
  • Effectue à la fois des recherches de mots-clés et sémantiques sur les magasins assistants et vectoriels de thread.
  • Reclasse les résultats de recherche pour sélectionner les résultats les plus pertinents avant de générer la réponse finale.
  • Par défaut, l’outil de recherche de fichiers utilise les paramètres suivants :
    • Taille de bloc : 800 jetons
    • Chevauchement des segments : 400 jetons
    • Modèle d’incorporation : text-embedding-3-large à 256 dimensions
    • Nombre maximal de blocs ajoutés au contexte : 20

Magasins vectoriels

Les objets de magasin de vecteurs donnent à l’outil de recherche de fichiers la possibilité de rechercher vos fichiers. L’ajout d’un fichier à un magasin de vecteurs l'analyse automatiquement, le divise en segments, l'intègre et le stocke dans une base de données vectorielle capable d'effectuer des recherches par mots-clés et recherches sémantiques. Chaque magasin de vecteurs peut contenir jusqu’à 10 000 fichiers. Les magasins de vecteurs peuvent être reliés aussi bien aux assistants qu'aux threads. Actuellement, vous pouvez attacher au maximum un vector store à un assistant et au maximum un vector store à un thread.

Création de magasins vectoriels et ajout de fichiers

Vous pouvez créer un magasin de vecteurs et y ajouter des fichiers dans un seul appel d’API :

vector_store = client.beta.vector_stores.create(
  name="Product Documentation",
  file_ids=['file_1', 'file_2', 'file_3', 'file_4', 'file_5']
)

L’ajout de fichiers à des magasins vectoriels est une opération asynchrone. Pour vous assurer que l’opération est terminée, nous vous recommandons d’utiliser les helpers « créer et interroger » dans nos kits SDK officiels. Si vous n’utilisez pas les kits sdk, vous pouvez récupérer l’objet vector_store et surveiller sa file_counts propriété pour voir le résultat de l’opération d’ingestion de fichier.

Les fichiers peuvent également être ajoutés à un magasin de vecteurs après sa création en créant des fichiers de magasin de vecteurs.

file = client.beta.vector_stores.files.create_and_poll(
  vector_store_id="vs_abc123",
  file_id="file-abc123"
)

Vous pouvez également ajouter plusieurs fichiers à un magasin vectoriel en créant des lots allant jusqu’à 500 fichiers.

batch = client.beta.vector_stores.file_batches.create_and_poll(
  vector_store_id="vs_abc123",
  file_ids=['file_1', 'file_2', 'file_3', 'file_4', 'file_5']
)

De même, ces fichiers peuvent être supprimés d’un magasin vectoriel en procédant comme suit :

  • Suppression de l'objet de fichier de stockage de vecteurs ou,
  • En supprimant l’objet de fichier sous-jacent (qui supprime le fichier de toutes les configurations vector_store et code_interpreter sur tous les assistants et threads de votre organisation)

La taille maximale du fichier est de 512 Mo. Chaque fichier ne doit contenir plus de 5 000 000 jetons par fichier (calculé automatiquement lorsque vous joignez un fichier).

Connexion de magasin de vecteurs

Vous pouvez attacher des magasins de vecteurs à votre Assistant ou Thread à l’aide du paramètre tool_resources.

assistant = client.beta.assistants.create(
  instructions="You are a helpful product support assistant and you answer questions based on the files provided to you.",
  model="gpt-4-turbo",
  tools=[{"type": "file_search"}],
  tool_resources={
    "file_search": {
      "vector_store_ids": ["vs_1"]
    }
  }
)

thread = client.beta.threads.create(
  messages=[ { "role": "user", "content": "How do I cancel my subscription?"} ],
  tool_resources={
    "file_search": {
      "vector_store_ids": ["vs_2"]
    }
  }
)

Vous pouvez également attacher un stockage de vecteurs aux Threads ou Assistants après leur création en les mettant à jour avec le bon tool_resources.

Garantir la préparation du magasin vectoriel avant la création d’exécutions

Nous vous recommandons vivement de vous assurer que tous les fichiers d’un vector_store sont entièrement traités avant de créer une exécution. Cela garantit que toutes les données de votre magasin vectoriel peuvent faire l’objet d’une recherche. Vous pouvez vérifier la disponibilité du vector store en utilisant les assistants de polling des SDK, ou en interrogeant manuellement l’objet vector_store afin de vous assurer que le statut est terminé.

En plan B, il y a un délai d'attente maximum de 60 secondes dans l'objet run lorsque le stockage vectoriel du thread contient des fichiers encore en cours de traitement. Cela permet de s’assurer que tous les fichiers que vos utilisateurs chargent dans un thread peuvent faire l’objet d’une recherche complète avant la poursuite de l’exécution. Ce délai de secours ne s'applique pas au magasin vectoriel de l'assistant.

Gestion des coûts avec des politiques d’expiration

L’outil file_search utilise l’objet vector_stores comme ressource et vous serez facturé en fonction de la taille des objets vector_store créés. La taille de l’objet de magasin de vecteurs est la somme de tous les blocs analysés de vos fichiers et de leurs incorporations correspondantes.

Pour vous aider à gérer les coûts associés à ces objets vector_store, nous avons ajouté la prise en charge des stratégies d’expiration dans l’objet vector_store . Vous pouvez définir ces stratégies lors de la création ou de la mise à jour de l’objet vector_store .

vector_store = client.beta.vector_stores.create_and_poll(
  name="Product Documentation",
  file_ids=['file_1', 'file_2', 'file_3', 'file_4', 'file_5'],
  expires_after={
	  "anchor": "last_active_at",
	  "days": 7
  }
)

Les magasins des vecteurs de threads possèdent des politiques d’expiration par défaut

Les ensembles de vecteurs créés à l'aide de threads d'exécution (comme tool_resources.file_search.vector_stores dans Threads ou message.attachments dans Messages) ont une stratégie d'expiration par défaut de sept jours après leur dernière utilisation (définie comme la dernière fois que l'ensemble vectoriel faisait partie d'un processus).

Lorsqu’un magasin de vecteurs expire, les exécutions sur ce thread échouent. Pour résoudre ce problème, vous pouvez recréer une nouvelle vector_store avec les mêmes fichiers et la rattacher au thread.

all_files = list(client.beta.vector_stores.files.list("vs_expired"))

vector_store = client.beta.vector_stores.create(name="rag-store")
client.beta.threads.update(
    "thread_abc123",
    tool_resources={"file_search": {"vector_store_ids": [vector_store.id]}},
)

for file_batch in chunked(all_files, 100):
    client.beta.vector_stores.file_batches.create_and_poll(
        vector_store_id=vector_store.id, file_ids=[file.id for file in file_batch]
    )