Partilhar via


Ferramenta de pesquisa de ficheiros do Azure OpenAI Assistants (Pré-visualização)

A Pesquisa de Ficheiros aumenta o conhecimento do Assistente externo ao seu modelo, como informações proprietárias do produto ou documentos fornecidos pelos utilizadores. O OpenAI analisa e fragmenta automaticamente os seus documentos, cria e armazena as incorporações e utiliza a pesquisa de vetores e de palavras-chave para obter conteúdo relevante para responder às consultas do utilizador.

Importante

  • A pesquisa de ficheiros tem custos adicionais além das taxas baseadas no token de utilização do Azure OpenAI.

Nota

  • A pesquisa de arquivos pode ingerir até 10.000 arquivos por assistente - 500 vezes mais do que antes. É rápida, suporta consultas paralelas através de pesquisas multi-thread e apresenta reclassificação e reescrita de consultas melhoradas.
    • O arquivo de vetores é um novo objeto da API. Depois de um ficheiro ser adicionado a um arquivo de vetores, é automaticamente analisado, fragmentado e incorporado, ficando pronto para ser pesquisado. Os arquivos de vetores podem ser utilizados entre assistentes e threads, o que simplifica a gestão de ficheiros e a faturação.
  • Adicionamos suporte para o tool_choice parâmetro que pode ser usado para forçar o uso de uma ferramenta específica (como pesquisa de arquivos, interpretador de código ou uma função) em uma execução específica.

Suporte à pesquisa de ficheiros

Regiões suportadas

A pesquisa de ficheiros está disponível em regiões que suportam Assistentes.

Versão da API

  • 2024-05-01-pré-visualização

Tipos de ficheiro suportados

Nota

Para tipos de texto/MIME, a codificação deve ser utf-8, utf-16 ou ASCII.

File format Tipo de MIME
c. texto/x-c
.cs texto/x-csharp
.cpp texto/x-c++
.doc aplicação/msword
.docx aplicativo/vnd.openxmlformats-officedocument.wordprocessingml.document
.html text/html
.java texto/x-java
.json application/json
.md texto/marcação
.pdf aplicação/pdf
.php texto/x-php
.pptx application/vnd.openxmlformats-officedocument.presentationml.presentation
.py texto/x-python
.py texto/x-script.python
.rb texto/x-rubi
.tex texto/x-tex
.txt text/plain
.css texto/css
.js texto/javascript
.sh aplicação/x-sh
.ts aplicação/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"}],
)

Para acessar seus arquivos, a ferramenta de pesquisa de arquivos usa o objeto de armazenamento vetorial. Carregue seus arquivos e crie um repositório vetorial para contê-los. Depois que o repositório vetorial for criado, você deve pesquisar seu status até que todos os arquivos estejam fora do estado para garantir que todo o conteúdo tenha terminado o in_progress processamento. O SDK fornece auxiliares para upload e sondagem.

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)

Atualizar o assistente para usar o novo repositório de vetores

Para tornar os ficheiros acessíveis ao seu assistente, atualize os do tool_resources assistente com o novo vector_store ID.

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

Criar um thread

Você também pode anexar arquivos como anexos de mensagem no seu thread. Isso criará outro vector_store associado ao thread ou, se já houver um repositório de vetores anexado a esse thread, anexará os novos arquivos ao repositório de vetores de thread existente. Quando você cria um Executar neste thread, a ferramenta de pesquisa de arquivos consultará o vector_store do seu assistente e o vector_store no 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)

Os repositórios de vetores são criados usando anexos de mensagens que têm uma política de expiração padrão de sete dias após terem sido ativos pela última vez (definidos como a última vez que o repositório de vetores fez parte de uma execução). Esse padrão existe para ajudá-lo a gerenciar seus custos de armazenamento vetorial. Você pode substituir essas políticas de expiração a qualquer momento.

Crie uma execução e verifique a saída

Crie uma Execução e observe que o modelo usa a ferramenta de pesquisa de arquivos para fornecer uma resposta à pergunta do usuário.

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()

Como funciona

A ferramenta de pesquisa de arquivos implementa várias práticas recomendadas de recuperação prontas para uso para ajudá-lo a extrair os dados certos de seus arquivos e aumentar as respostas do modelo. A ferramenta file_search:

  • Reescreve as consultas do usuário para otimizá-las para pesquisa.
  • Divide consultas complexas de usuários em várias pesquisas que podem ser executadas em paralelo.
  • Executa pesquisas semânticas e de palavras-chave em repositórios de vetores de assistente e thread.
  • Reclassifica os resultados da pesquisa para escolher os mais relevantes antes de gerar a resposta final.
  • Por padrão, a ferramenta de pesquisa de arquivos usa as seguintes configurações:
    • Tamanho do bloco: 800 tokens
    • Sobreposição de blocos: 400 tokens
    • Modelo de incorporação: text-embedding-3-large em 256 dimensões
    • Número máximo de partes adicionadas ao contexto: 20

Repositórios vetoriais

Os objetos de armazenamento vetorial dão à ferramenta de pesquisa de arquivos a capacidade de pesquisar seus arquivos. Adicionar um arquivo a um repositório vetorial analisa, fragmenta, incorpora e armazena automaticamente o arquivo em um banco de dados vetorial capaz de pesquisa semântica e de palavras-chave. Cada armazenamento vetorial pode armazenar até 10.000 arquivos. Os armazenamentos vetoriais podem ser anexados a Assistentes e Threads. Atualmente, você pode anexar no máximo um repositório de vetores a um assistente e, no máximo, um armazenamento de vetores a um thread.

Criação de repositórios vetoriais e adição de arquivos

Você pode criar um repositório vetorial e adicionar arquivos a ele em uma única chamada de API:

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

Adicionar arquivos a repositórios vetoriais é uma operação assíncrona. Para garantir que a operação seja concluída, recomendamos que você use os auxiliares de 'criar e pesquisar' em nossos SDKs oficiais. Se você não estiver usando os SDKs, poderá recuperar o vector_store objeto e monitorar sua file_counts propriedade para ver o resultado da operação de ingestão de arquivos.

Os ficheiros também podem ser adicionados a um arquivo de vetores depois deste ser criado.

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

Como alternativa, você pode adicionar vários arquivos a um repositório vetorial criando lotes de até 500 arquivos.

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']
)

Da mesma forma, estes ficheiros podem ser removidos de um arquivo de vetores ao:

  • Eliminar o objeto de ficheiro do arquivo de vetores.
  • Eliminar o objeto de ficheiro subjacente (que remove o ficheiro de todas as configurações de vetor_store e code_interpreter em todos os assistentes e threads na sua organização).

O tamanho máximo do ficheiro é de 512 MB. Cada ficheiro não deve conter mais de 5 000 000 tokens por ficheiro (calculado automaticamente quando anexa um ficheiro).

Anexando repositórios vetoriais

Você pode anexar armazenamentos de vetores ao seu Assistente ou Thread usando o parâmetro 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"]
    }
  }
)

Você também pode anexar um repositório de vetores a Threads ou Assistentes depois que eles forem criados, atualizando-os com o direito tool_resources.

Garantindo a prontidão do armazenamento vetorial antes de criar execuções

É altamente recomendável que você garanta que todos os arquivos em um vetor_store sejam totalmente processados antes de criar uma execução. Isso garante que todos os dados em seu armazenamento de vetores sejam pesquisáveis. Você pode verificar a prontidão do armazenamento de vetores usando os auxiliares de sondagem nos SDKs ou sondando manualmente o vector_store objeto para garantir que o status seja concluído.

Como fallback, há uma espera máxima de 60 segundos no objeto run quando o armazenamento vetorial do thread contém arquivos que ainda estão sendo processados. Isso é para garantir que todos os arquivos que seus usuários carregam em um thread sejam totalmente pesquisáveis antes que a execução prossiga. Essa espera de fallback não se aplica ao armazenamento de vetores do assistente.

Gerenciando custos com políticas de expiração

A file_search ferramenta usa o vector_stores objeto como seu recurso e você será cobrado com base no tamanho dos vetor_store objetos criados. O tamanho do objeto de armazenamento de vetor é a soma de todos os blocos analisados de seus arquivos e suas incorporações correspondentes.

Para ajudá-lo a gerenciar os custos associados a esses objetos vetor_store, adicionamos suporte para políticas de expiração no vector_store objeto. Você pode definir essas políticas ao criar ou atualizar o vector_store objeto.

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
  }
)

Os repositórios de vetores de thread têm políticas de expiração padrão

Os repositórios de vetores criados usando auxiliares de thread (como tool_resources.file_search.vector_stores em Threads ou message.attachments em Mensagens) têm uma política de expiração padrão de sete dias após terem sido ativos pela última vez (definidos como a última vez que o repositório de vetores fez parte de uma execução).

Quando um repositório vetorial expira, as execuções nesse thread falharão. Para corrigir isso, você pode recriar um novo vetor_store com os mesmos arquivos e reanexá-lo ao 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]
    )