Quickstart Guide: Using OpenAI’s Vector Store Search Endpoint
Forward
I had to gather all the resources into one to power this AI assisted compilation…
I don’t care enough right now to actually go after making a robust database to search to offer more practicality and example…
Introduction
OpenAI’s Vector Store Search Endpoint enables developers to query and retrieve highly relevant document chunks from a custom vector store hosted within OpenAI’s API infrastructure. This endpoint is powerful for retrieval-augmented generation (RAG), where applications rely on external knowledge sources to provide up-to-date or customized responses.
If you’re familiar with OpenAI’s Assistants API, you may have encountered the file_search
tool, which internally uses this same vector store search endpoint. However, when designing custom applications, you’ll directly interact with this vector store search endpoint through RESTful API calls, as native SDK support has not yet been provided.
This guide introduces:
- The conceptual framework of the vector store search
- API usage examples and structures
- Python implementation examples to demonstrate how you can start leveraging the vector store endpoint immediately
Understanding the Vector Store Search API
The vector store search endpoint accepts search queries and optional filtering based on user-defined metadata attributes attached to files in your vector store. Metadata attributes (key-value pairs you define) significantly enhance querying flexibility, allowing fine-grained control over the retrieval process.
This is also powered by the vector store API endpoint itself and the different parameters you can set on it for adding and chunking files.
Example API Request
We’ll start with OpenAI’s example for CURL, giving both a URL, headers (-H), and demonstrating the JSON body of a http POST request.
curl -X POST \
https://api.openai.com/v1/vector_stores/vs_abc123/search \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "What is the return policy?",
"filters": {
"type": "eq",
"key": "document_type",
"value": "pdf"
},
"max_num_results": 10
}'
Example API Response
{
"object": "vector_store.search_results.page",
"search_query": "What is the return policy?",
"data": [
{
"file_id": "file_123",
"filename": "policy_document.pdf",
"score": 0.95,
"attributes": {
"author": "Jane Doe",
"date": "2023-01-10"
},
"content": [
{
"type": "text",
"text": "Relevant chunk of text."
}
]
}
],
"has_more": false,
"next_page": null
}
Managing Vector Store Files and Attributes
When you add files to your vector store, you can associate user-defined attributes to each file, allowing sophisticated and structured search queries.
Adding Files to a Vector Store Example
curl https://api.openai.com/v1/vector_stores/vs_abc123/files \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-H "OpenAI-Beta: assistants=v2" \
-d '{
"file_id": "file-abc123",
"attributes": {
"author": "John Doe",
"department": "Support",
"verified": true
}
}'
Practical Python Implementation
Since OpenAI’s official SDK does not yet offer built-in methods for interacting directly with the vector store search endpoint, we use Python’s httpx
library to build a streamlined client ourselves. Below is a concise yet robust example of how to accomplish this.
Step 1: Prepare Environment and Dependencies
First, ensure you have httpx
installed:
pip install httpx
Set your OpenAI API key:
export OPENAI_API_KEY='your-api-key'
Example Jupyter Notebook Style Implementation
Below I adopt a Jupyter notebook style by interleaving code blocks and detailed explanations, making it easy to follow along step by step.
Importing Required Libraries and Defining API Key Management
import httpx
import os
def _get_headers():
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:
raise ValueError("OPENAI_API_KEY environment variable not set.")
return {'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'}
This step ensures that we securely handle the API key using environment variables.
Defining the Vector Store Search Function
We encapsulate API interactions into a reusable Python function:
def vector_store_search(vector_store_id, query, filters=None, max_num_results=10, rewrite_query=False):
endpoint = f"https://api.openai.com/v1/vector_stores/{vector_store_id}/search"
payload = {
"query": query,
"max_num_results": max_num_results,
"rewrite_query": rewrite_query
}
if filters:
payload["filters"] = filters
response = httpx.post(endpoint, headers=_get_headers(), json=payload)
response.raise_for_status()
return response.json()
This function clearly demonstrates the structure of the API payload, allowing easy modification for filtering.
Demonstrating a Human-Readable Output of Search Results
A helpful method to print the returned search data cleanly:
def display_results(results):
print(f"Query: {results['search_query']}\n{'-'*40}")
for item in results['data']:
print(f"Filename: {item['filename']} (Score: {item['score']:.2f})")
print(f"Attributes: {item['attributes']}")
print(f"Content Preview: {item['content'][0]['text'][:100]}...\n{'-'*40}")
This makes your returned data immediately accessible and understandable.
Example Interactive Query and Output
Finally, we demonstrate how easily this integrates into applications:
if __name__ == "__main__":
vector_store_id = "vs_abc123"
user_query = input("Enter your search query: ").strip()
# Example: A hypothetical filter (commented-out)
# filters = {
# "type": "and",
# "filters": [
# {"key": "author", "type": "eq", "value": "Jane Doe"},
# {"key": "verified", "type": "eq", "value": True}
# ]
# }
search_results = vector_store_search(
vector_store_id=vector_store_id,
query=user_query,
# filters=filters, # Uncomment to use custom metadata filters
max_num_results=5,
rewrite_query=True
)
display_results(search_results)
This example succinctly highlights how developers can integrate queries into practical workflows and customize metadata filters according to their application’s unique requirements.
Potential Applications of Vector Store Search API
Retrieval-Augmented Generation (RAG):
Use retrieved document chunks as context for generating detailed and context-aware responses in LLM applications.
Customer Support Systems:
Quickly retrieve answers from large knowledge bases, filtering by metadata such as document author, status, or versioning.
Legal and Compliance Review:
Efficiently search regulatory documents, filtering by effective dates, compliance status, or jurisdiction metadata.
Your API reference - no clicking and expanding
Vector Store Search API Request Body Parameters
Required Parameters
query
(string or array)
The query string or array for performing the search.Optional Parameters
filters
(object)
Filters based on file attributes to narrow the search results.Filters Types:
Comparison Filter (object)
Compares a specified attribute key against a given value using a comparison operator.
key
(string, required)
Attribute key for comparison.
type
(string, required)
Comparison operator. Supported operators:
eq
: equalsne
: not equalgt
: greater thangte
: greater than or equallt
: less thanlte
: less than or equal
value
(string, number, boolean, required)
The value to compare against the attribute key.Compound Filter (object)
Combines multiple filters using logical operators.
filters
(array, required)
An array of filters to combine. Elements can be either:
ComparisonFilter
CompoundFilter
(nested)
type
(string, required)
Logical operator to combine filters. Supported operators:
and
or
max_num_results
(integer, default: 10)
Maximum number of results to return (1 to 50 inclusive).
ranking_options
(object)
Ranking options for fine-tuning the search results.
rewrite_query
(boolean, default: false)
Determines if the natural language query should be rewritten for vector search.
Costs
Review both the cost of persistent storage of vector stores AND the cost of making calls, currently only described as a Responses endpoint file search tool call price of $2.50/1k
https://platform.openai.com/docs/pricing
Wrapping Up
By carefully understanding and using this Vector Store Search Endpoint, developers gain a powerful tool for building intelligent, contextually aware applications. Leveraging user-defined attributes greatly enhances retrieval precision, facilitating advanced workflows and efficient content management in AI applications.
A complete ready-to use Python module providing this method:
search_results = vector_store_search(
vector_store_id=vector_store_id,
query=user_query,
# filters=filters, # Uncomment to use, None also possible
max_num_results=5,
rewrite_query=True
)
Full code from before
import httpx
import os
from typing import Optional, Union, List, Dict, Any
def _get_headers() -> dict[str, str]:
api_key = os.getenv('OPENAI_API_KEY')
if not api_key:
raise ValueError("Please set the OPENAI_API_KEY environment variable.")
return {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
def vector_store_search(
vector_store_id: str,
query: Union[str, List[str]],
filters: Optional[Dict[str, Any]] = None,
max_num_results: Optional[int] = 10,
rewrite_query: Optional[bool] = False,
ranking_options: Optional[Dict[str, Any]] = None
) -> Dict[str, Any]:
"""
Searches a vector store for relevant chunks based on a query and optional file attribute filters.
Parameters:
vector_store_id (str): ID of the target vector store.
query (str | List[str]): Search query (string or list of strings).
filters (dict, optional): Filters based on metadata attributes.
max_num_results (int, optional): Maximum results (default is 10, max 50).
rewrite_query (bool, optional): Whether to rewrite the natural language query for vector search.
ranking_options (dict, optional): Additional ranking options for the search.
Returns:
dict: JSON response from the API including matched chunks and metadata.
"""
endpoint = f"https://api.openai.com/v1/vector_stores/{vector_store_id}/search"
payload = {
"query": query,
"max_num_results": max_num_results,
"rewrite_query": rewrite_query
}
if filters:
payload["filters"] = filters
if ranking_options:
payload["ranking_options"] = ranking_options
response = httpx.post(
endpoint,
headers=_get_headers(),
json=payload,
timeout=60,
)
response.raise_for_status()
return response.json()
def display_search_results(search_response: Dict[str, Any]):
"""
Nicely formats and prints search results from the vector store search response.
Parameters:
search_response (dict): The JSON response returned from vector_store_search function.
"""
print(f"\nSearch Query: '{search_response.get('search_query')}'")
print(f"{'-'*50}")
for idx, result in enumerate(search_response.get('data', []), start=1):
file_id = result.get('file_id')
filename = result.get('filename')
score = result.get('score')
attributes = result.get('attributes', {})
author = attributes.get('author', 'N/A')
date = attributes.get('date', 'N/A')
print(f"Result {idx}:")
print(f" File ID: {file_id}")
print(f" Filename: {filename}")
print(f" Score: {score}")
print(f" Author: {author}")
print(f" Date: {date}")
print(" Content:")
for chunk in result.get('content', []):
content_preview = chunk.get('text', '[No Content]')
print(f" - {content_preview[:100]}{'...' if len(content_preview) > 100 else ''}")
print(f"{'-'*50}")
if __name__ == "__main__":
# Example vector store ID from your OpenAI dashboard.
VECTOR_STORE_ID = "vs_abc123"
user_query = input("Enter your search query: ").strip()
# Hypothetical usage of metadata attributes for filtering.
# Example: Filter to documents authored by "John Doe" created after January 1, 2023.
'''
filters_example = {
"type": "and",
"filters": [
{"key": "author", "type": "eq", "value": "John Doe"},
{"key": "date", "type": "gte", "value": "2023-01-01"}
]
}
'''
try:
# Simple search example without filters.
response = vector_store_search(
vector_store_id=VECTOR_STORE_ID,
query=user_query,
max_num_results=5,
rewrite_query=True,
# filters=filters_example # Uncomment to use attribute filtering.
)
display_search_results(response)
except httpx.HTTPError as e:
print(f"HTTP error occurred: {e}")
except Exception as e:
print(f"Unexpected error occurred: {e}")