共用方式為


Azure OpenAI 助理檔案搜尋工具 (預覽)

檔案搜尋會以來自其模型外部的知識 (例如使用者提供的專屬產品資訊或文件) 來增強助理。 OpenAI 會自動剖析並對文件分區、建立及儲存內嵌,並使用向量和關鍵字搜尋來擷取相關內容來回應使用者查詢。

重要

  • 檔案搜尋除了 Azure OpenAI 使用量的權杖費用之外,還有額外的費用

注意

  • 檔案搜尋可以內嵌每個助理最多 10,000 個檔案 - 比之前多 500 倍。 其速度很快,可透過多對話搜尋支援平行查詢,以及增強重新排名和查詢重寫的功能。
    • 向量存放區是 API 中的新物件。 一旦檔案新增至向量存放區,它就會自動進行剖析、區塊化和內嵌,並準備好提供搜尋。 向量存放區可以跨助理和對話使用,簡化檔案管理和計費。
  • 我們已新增 tool_choice 參數的支援,可用來強制在特定執行中使用特定工具 (例如檔案搜尋、程式碼解譯器或函式)。

檔案搜尋支援

支援的區域

支援助理的區域中提供檔案搜尋。

API 版本

  • 2024-05-01-preview

支援的檔案類型

注意

針對 text/MIME 類型,編碼必須是 utf-8、utf-16 或 ASCII。

檔案格式 MIME 類型
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 應用程式/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 text/plain
.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"}],
)

若要存取您的檔案,檔案搜尋工具會使用向量存放區物件。 上傳您的檔案,並建立向量存放區以包含它們。 建立向量存放區之後,您應該輪詢其狀態,直到所有檔案都脫離 in_progress 狀態,以確保所有內容都已完成處理。 SDK 提供上傳和輪詢的協助程式。

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)

更新助理以使用新的向量存放區

若要讓助理可存取檔案,請使用新的 vector_store 識別碼更新助理的 tool_resources

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

建立執行緒

您也可以將檔案連結為執行緒上的訊息連結。 這樣做會建立與執行緒相關聯的另一個 vector_store,或者,如果已有連結至此執行緒的向量存放區,請將新檔案連結至現有的執行緒向量存放區。 當您在此執行緒上建立「執行」時,檔案搜尋工具會同時從助理和執行緒上的 vector_store 查詢 vector_store

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

向量存放區是使用訊息連結來建立,其預設到期原則為上次作用中 (定義為向量存放區屬於執行的最後時間) 後的七天。 此預設值可協助您管理向量儲存成本。 您可以隨時覆寫這些到期原則。

建立執行並檢查輸出

建立執行並觀察模型使用檔案搜尋工具來提供使用者問題的回應。

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

運作方式

檔案搜尋工具會實作數個現成的擷取最佳做法,以協助您從檔案擷取正確的資料,並增強模型的回應。 file_search 工具:

  • 重寫使用者查詢以將其最佳化進行搜尋。
  • 將複雜的使用者查詢細分為可以平行執行的多個搜尋。
  • 跨助理和執行緒向量存放區執行關鍵字和語意搜尋。
  • 在產生最終回應之前,重新調整搜尋結果以挑選最相關的搜尋結果。
  • 依預設,檔案搜尋工具會使用下列設定:
    • 區塊大小:800 個權杖
    • 區塊重疊:400 個權杖
    • 內嵌模型:256 維度的 text-embedding-3-large
    • 新增至內容的最大區塊數目:20

向量存放區

向量存放區物件可讓檔案搜尋工具搜尋您的檔案。 將檔案新增至向量存放區會自動剖析、分區、內嵌,並將檔案儲存在能夠具備關鍵字和語意搜尋的向量資料庫中。 每個向量存放區最多可以保存 10,000 個檔案。 向量存放區可以連結至助理和執行緒。 您目前最多可以將一個向量存放區連結至助理,且最多可以將一個向量存放區連結至執行緒。

建立向量存放區和新增檔案

您可以在單一 API 呼叫中建立向量存放區,並將檔案新增至其中:

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

將檔案新增至向量存放區是非同步作業。 若要確保作業已完成,建議您使用我們的官方 SDK 中的「建立和輪詢」協助程式。 如果未使用 SDK,您可以擷取 vector_store 物件並監視其 file_counts 屬性,以查看檔案擷取作業的結果。

建立向量存放區檔案之後,也可以將檔案新增至向量存放區。

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

或者,您可以建立最多 500 個檔案的批次,將數個檔案新增至向量存放區。

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

同樣地,這些檔案也可以透過下列其中一個方式從向量存放區移除:

  • 刪除向量存放區檔案物件,或
  • 藉由刪除基礎檔案物件 (這會從組織中所有助理和執行緒的所有 vector_store 和 code_interpreter 設定中移除該檔案)

檔案大小上限是 512 MB。 每個檔案應包含每個檔案不超過 5,000,000 個權杖 (當您連結檔案時自動計算)。

連結向量存放區

您可以使用 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"]
    }
  }
)

您也可以將向量存放區連結至執行緒或助理,方法是使用正確的 tool_resources 更新它們。

建立執行之前確保向量存放區整備

強烈建議您在建立執行之前,先確保 vector_store 中的所有檔案都已完整處理。 這可確保向量存放區中的所有資料都可搜尋。 您可以使用 SDK 中的輪詢協助程式,或手動輪詢 vector_store 物件以確保狀態為已完成,來檢查向量存放區整備程度。

作為後援,當執行緒的向量存放區包含仍在處理的檔案時,執行物件中會有 60 秒的最大等候時間。 這是為了確保您的使用者在執行緒中上傳的任何檔案,在繼續執行之前完全可供搜尋。 此後援等候不適用助理的向量存放區。

使用到期原則管理成本

file_search 工具會使用 vector_stores 物件作為其資源,而您會根據建立的 vector_store 物件的大小來計費。 向量存放區物件的大小是從檔案及其對應內嵌剖析的所有區塊的總和。

為了協助您管理與這些 vector_store 物件相關聯的成本,我們已在 vector_store 物件中新增到期原則的支援。 您可以在建立或更新 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
  }
)

執行緒向量存放區有預設到期原則

使用執行緒協助程式 (例如在執行緒中的 tool_resources.file_search.vector_stores 或訊息中的 message.attachments) 建立的向量存放區,其預設到期原則為上次使用中 (定義為向量存放區屬於執行的最後時間) 後的七天。

當向量存放區過期時,在該執行緒上的執行將會失敗。 若要修正此問題,您可以使用相同的檔案重新建立新的 vector_store,並將其重新連結至執行緒。

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