llama-index vector_stores Tencent Cloud COS Vectors integration
Project description
LlamaIndex Vector Stores Integration: Tencent Cloud COS Vectors
English | 中文
llama-index-vector-stores-cos integrates Tencent Cloud COS Vectors with LlamaIndex, letting you use COS Vectors as the backend of a VectorStoreIndex for vector insertion, retrieval, and metadata filtering — with zero ops overhead.
- PyPI:
llama-index-vector-stores-cos - Python:
>=3.10, <3.14 - License: MIT
Features
- 🚀 Plug & play: swap in as your
VectorStoreIndexbackend in a single line; works with any LlamaIndexQueryEngine/Retriever. - 🧩 Standard interface: implements
BasePydanticVectorStorewith fulladd/query/get_nodes/delete/delete_nodes/clear, plus asynca*counterparts. - 🔎 Rich filtering: supports the standard LlamaIndex
MetadataFilters—EQ/NE/GT/GTE/LT/LTE/IN/NIN/IS_EMPTYcombined withAND/OR. - 🛡 Built-in throttling: write token bucket at 5 req/s to stay safely below service limits.
- ☁️ Fully managed: both the vector bucket and the index are hosted on Tencent Cloud COS Vectors — no self-hosted vector database required.
Installation
Install the main package (assuming it's already published to PyPI):
pip install llama-index-vector-stores-cos
Install LlamaIndex ecosystem components as needed (examples below use OpenAI):
# Embedding & LLM (pick what you need)
pip install llama-index-embeddings-openai llama-index-llms-openai
# Or local Ollama
# pip install llama-index-embeddings-ollama
# Or HuggingFace
# pip install llama-index-embeddings-huggingface
Enable COS Vectors
Full guide: https://www.tencentcloud.com/document/product/436 (or https://cloud.tencent.com/document/product/436 in Chinese).
Quick steps:
-
Log in to the Tencent Cloud Console and enable Cloud Object Storage (COS).
-
Enable COS Vectors and create a vector bucket in your target region (e.g.
ap-guangzhou). -
Go to CAM and create (or reuse) an API key pair (
SecretId+SecretKey). -
Grab the vector bucket's dedicated access domain, in the form of:
vectors.<region>.coslake.com # e.g. vectors.ap-guangzhou.coslake.com
⚠️
Domainmust be the COS Vectors dedicated domain (vectors.<region>.coslake.com), not the regular COS domaincos.<region>.myqcloud.com. Using the wrong one leads to access failures.
Recommended: inject credentials via environment variables:
export COS_SECRET_ID=your_secret_id
export COS_SECRET_KEY=your_secret_key
export OPENAI_API_KEY=your_openai_api_key
Embedding model
This document uses OpenAI text-embedding-3-small (1536 dim) as the minimal example. You can swap in OllamaEmbedding, HuggingFaceEmbedding, or any LlamaIndex BaseEmbedding implementation — just make sure the dimension you pass when creating the index matches the embedding model's output dimension.
from llama_index.core import Settings
from llama_index.embeddings.openai import OpenAIEmbedding
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small") # 1536 dim
Quick start
1. Create a new index and get a VectorStore
create_index_from_bucket creates an index in the specified vector bucket and returns a ready-to-use COSVectorStore.
import os
from qcloud_cos import CosConfig
from llama_index.vector_stores.cos import COSVectorStore
config = CosConfig(
Region="ap-guangzhou",
SecretId=os.environ["COS_SECRET_ID"],
SecretKey=os.environ["COS_SECRET_KEY"],
Domain="vectors.ap-guangzhou.coslake.com",
)
vector_store = COSVectorStore.create_index_from_bucket(
bucket_name="mybucket-1253960454",
index_name="my-index",
dimension=1536, # must match the embedding output
distance_metric="cosine", # or "euclidean"
config=config,
)
2. Reuse an existing index
If the index already exists, just construct a COSVectorStore directly:
from qcloud_cos import CosConfig, CosVectorsClient
from llama_index.vector_stores.cos import COSVectorStore
client = CosVectorsClient(CosConfig(
Region="ap-guangzhou",
SecretId=os.environ["COS_SECRET_ID"],
SecretKey=os.environ["COS_SECRET_KEY"],
Domain="vectors.ap-guangzhou.coslake.com",
))
vector_store = COSVectorStore(
bucket_name="mybucket-1253960454",
index_name="my-index",
client=client, # or pass config=CosConfig(...)
)
At least one of
client/configis required; if both are provided,clientwins.
Usage examples
Insert vectors
From text (TextNode)
from llama_index.core.schema import TextNode
from llama_index.core import Settings
nodes = [
TextNode(text="The Oriental Pearl Tower sits by the Huangpu River in Shanghai.", metadata={"city": "shanghai"}),
TextNode(text="The Forbidden City was the imperial palace of the Ming and Qing dynasties.", metadata={"city": "beijing"}),
]
for n in nodes:
n.embedding = Settings.embed_model.get_text_embedding(n.get_content())
vector_store.add(nodes)
From documents (SimpleDirectoryReader)
from llama_index.core import VectorStoreIndex, StorageContext, SimpleDirectoryReader
documents = SimpleDirectoryReader("./data").load_data()
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
Retrieve vectors
Plain similarity search
retriever = index.as_retriever(similarity_top_k=3)
nodes = retriever.retrieve("Where is the Oriental Pearl Tower?")
for n in nodes:
print(n.score, n.text[:80])
Or use the query engine directly:
query_engine = index.as_query_engine(similarity_top_k=3)
print(query_engine.query("Where is the Oriental Pearl Tower?"))
Metadata-filtered search
from llama_index.core.vector_stores import (
MetadataFilter,
MetadataFilters,
FilterOperator,
FilterCondition,
)
filters = MetadataFilters(
filters=[
MetadataFilter(key="city", value="shanghai", operator=FilterOperator.EQ),
MetadataFilter(key="tags", value=["landmark", "tourism"], operator=FilterOperator.IN),
],
condition=FilterCondition.AND, # OR is also supported; NOT is NOT supported
)
retriever = index.as_retriever(similarity_top_k=5, filters=filters)
nodes = retriever.retrieve("What landmarks are in Shanghai?")
Supported operators: EQ / NE / GT / GTE / LT / LTE / IN / NIN / IS_EMPTY. Conditions: AND / OR. See Parameters.
Node management
# Fetch nodes by ID
nodes = vector_store.get_nodes(node_ids=["node-id-1", "node-id-2"])
# Delete nodes by ID
vector_store.delete_nodes(node_ids=["node-id-1"])
# Delete all nodes belonging to a source doc (matched by metadata ref_doc_id)
vector_store.delete(ref_doc_id="doc-id-xxx")
# ⚠️ Destroy the whole index (dangerous — this is NOT a "truncate")
vector_store.clear()
delete_nodesdoes not support thefiltersargument;clear()callsdelete_indexdirectly.
End-to-end LlamaIndex example
A minimal runnable pipeline: load documents → build index → ask questions.
import os
from qcloud_cos import CosConfig
from llama_index.core import (
Settings,
SimpleDirectoryReader,
StorageContext,
VectorStoreIndex,
)
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.llms.openai import OpenAI
from llama_index.vector_stores.cos import COSVectorStore
# 1. Configure embedding & LLM
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small") # 1536 dim
Settings.llm = OpenAI(model="gpt-4o-mini")
# 2. Connect to COS Vectors
config = CosConfig(
Region="ap-guangzhou",
SecretId=os.environ["COS_SECRET_ID"],
SecretKey=os.environ["COS_SECRET_KEY"],
Domain="vectors.ap-guangzhou.coslake.com",
)
# 3. Create a new index (use COSVectorStore(...) directly if the index already exists)
vector_store = COSVectorStore.create_index_from_bucket(
bucket_name="mybucket-1253960454",
index_name="llama-index-demo",
dimension=1536,
distance_metric="cosine",
config=config,
)
# 4. Read local docs → insert vectors
documents = SimpleDirectoryReader("./data").load_data()
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, storage_context=storage_context)
# 5. Query
query_engine = index.as_query_engine(similarity_top_k=3)
print(query_engine.query("What is this document mainly about?"))
Parameters
COSVectorStore(...) constructor
| Param | Type | Default | Description |
|---|---|---|---|
bucket_name |
str |
required | COS vector bucket name. |
index_name |
str |
required | Index name. |
data_type |
str |
"float32" |
Vector data type. |
insert_batch_size |
int |
500 |
Max items per write batch; upper bound is 500, otherwise ValueError. |
text_field |
Optional[str] |
None |
If set, restore TextNode.text from this metadata key; otherwise use the default serializer. |
distance_metric |
str |
"cosine" |
Distance metric; supports "cosine" and "euclidean". |
client |
Optional[CosVectorsClient] |
None |
Pre-built client; one of client/config is required. |
config |
Optional[CosConfig] |
None |
Used to build the client internally; one of client/config is required. |
COSVectorStore.create_index_from_bucket(...) extra params
| Param | Type | Default | Description |
|---|---|---|---|
dimension |
int |
required | Vector dimension; must match the embedding output. |
non_filterable_metadata_keys |
Optional[List] |
None |
Metadata keys that cannot be used as filters; _node_content and _node_type are always appended automatically. |
Supported filter operators
| Operator | Supported | Notes |
|---|---|---|
EQ |
✅ | equals |
NE |
✅ | not equal |
GT/GTE |
✅ | greater (or eq) |
LT/LTE |
✅ | less (or eq) |
IN |
✅ | value in list |
NIN |
✅ | value not in |
IS_EMPTY |
✅ | field missing |
TEXT_MATCH / CONTAINS / others |
❌ | not supported |
| Condition | Supported |
|---|---|
AND |
✅ |
OR |
✅ |
NOT |
❌ |
Limits & notes
addhas a built-in token-bucket rate limit of 5 req/s; large writes will auto-sleep.insert_batch_sizeis capped at 500.queryonly supportsVectorStoreQueryMode.DEFAULT; passingHYBRID/SPARSEraisesNotImplementedError.get_nodesrequiresnode_ids;filtersis currently ignored.delete_nodesdoes not supportfilters;node_idsis required.clear()callsdelete_indexand destroys the whole index — use with care.- Every core method has an async counterpart:
async_add/aquery/aget_nodes/adelete/adelete_nodes/aclear.
FAQ
Q1: ValueError: Either 'client' or 'config' must be provided.
You passed neither client nor config when constructing COSVectorStore (or calling create_index_from_bucket). Provide at least one.
Q2: ValueError: insert_batch_size must be <= 500
COS Vectors caps batched writes at 500. Lower insert_batch_size.
Q3: ValueError: NOT condition is not supported for COS Vectors filters
FilterCondition.NOT is not supported. Rewrite with NE / NIN instead.
Q4: NotImplementedError: Only DEFAULT query mode is supported for COSVectorStore
Make sure you're using the default query mode; do not pass VectorStoreQueryMode.HYBRID / SPARSE etc.
Q5: Access fails and returns an XML-formatted error message
In most cases, Domain is missing, or it was set to the regular COS domain (for example, cos.<region>.myqcloud.com). Use the COS Vectors dedicated domain vectors.<region>.coslake.com instead.
Q6: What is text_field and when do I need it?
By default, COSVectorStore serializes the full node into metadata (key _node_content) and rebuilds the TextNode on read. If you'd rather restore text from a custom metadata field (e.g. content), set text_field="content"; that field must exist in the metadata you write.
Q7: Dimension mismatch error
The dimension you pass to create_index_from_bucket must exactly match your embedding model's output dimension (OpenAI text-embedding-3-small = 1536, bge-m3 = 1024, etc.).
Q8: What does clear() actually do?
It calls delete_index and destroys the whole index, not just its data. After calling it you'll need to recreate the index via create_index_from_bucket.
License
Released under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file llama_index_vector_stores_cos-0.1.0.tar.gz.
File metadata
- Download URL: llama_index_vector_stores_cos-0.1.0.tar.gz
- Upload date:
- Size: 10.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a92debe134fae7e224da70a18ef0191096fc029353a9ae784185562f3a4ccc3
|
|
| MD5 |
5d98e8c0e43a42c06d24283c6ae545b1
|
|
| BLAKE2b-256 |
c5cba7b108fed0dc7985075246e6d6f8d0564cb0a5cbfc7457a984abfb45daf2
|
File details
Details for the file llama_index_vector_stores_cos-0.1.0-py3-none-any.whl.
File metadata
- Download URL: llama_index_vector_stores_cos-0.1.0-py3-none-any.whl
- Upload date:
- Size: 10.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77e3be36705b0bab38ed89811ea0b184752b7a2be0ba5d2b69c2b4cbb433729f
|
|
| MD5 |
896cbcd9faafd22f45eb33bd565ce3a8
|
|
| BLAKE2b-256 |
6cc4b284b816f37c2ae91c3cf8deac693adc88085de836aadd135ae1da346b47
|