upsert 异步生效,写入后立刻 search 可能查不到;v10 起 create 改用 schema/deployment,旧 spec/dimension 写法需迁移;不同方式创建的索引要用对应的 upsert/query 或 upsert_records/search 方法
python-sdk
pinecone-ioApache-2.0活跃维护Pinecone 向量数据库的官方 Python SDK,方便在 Python 项目里直接接入向量存储和相似度检索,搭建 RAG 应用时不用自己封装 API。
Official Python SDK for the Pinecone vector database
pip install pineconeREADME 未说明,仅要求 Python 3.10+,无需本地 GPU 或显存
Pinecone 向量数据库官方 Python SDK,用来建索引、读写文档和做向量检索
Pinecone 向量数据库的官方 Python SDK,方便在 Python 项目里直接接入向量存储和相似度检索,搭建 RAG 应用时不用自己封装 API。
核心能力
- 用 schema 声明字段创建文档索引
- 通过 index.documents 批量 upsert 与 search 文档
- 提供 AsyncPinecone 异步客户端配合 asyncio
- 支持按字段做 DenseVectorQuery 向量相似检索
- 可配置请求超时与 PINECONE_DEBUG 日志
容易踩的坑
- v10.3.0Release v10.3.0最新正式版2026-11-03 · 2026-11-03 00:17 UTC
10.3.0 adds two integrated-embedding settings for document indexes, from Silas Smith (@ssmith-pc): a per-search query task and a processing location. It also fixes gRPC through authenticating proxies. Nothing is removed or renamed; the API version is still
2026-07.Act only if you give the gRPC client a
proxy_urlthat isn'thttp://(see Behavior change), or your logs captured aPineconeConfigorConfigrepr with a proxy password (rotate it).What's new
Set the query task per search:
EmbedQuery.parameters(docs, 3b6923e)EmbedQuery(field=..., query=..., parameters: dict[str, Any] | None = None)overrides the field'sread_parametersfor one search.- One field serves several query types: a
gemini-embedding-2field indexed for retrieval can also answer fact-checking queries, with no second index or re-embedding. - Only
task_typecan be set today; the server validates it.pc.inference.list_models()lists the models that accept it. - Unset, the field's
read_parametersapply and the key is not sent.SparseEmbedQuerydoes not take it.
from pinecone import EmbedQuery, Pinecone pc = Pinecone() facts = pc.index("fact-checks") # "body" embeds with gemini-embedding-2 results = facts.documents.search( namespace="claims-en", top_k=5, score_by=[ EmbedQuery( field="body", query="Is the Eiffel Tower taller than 300 m?", parameters={"task_type": "fact_verification"}, ) ], )Choose where your text is processed:
FieldEmbedConfig.processing_location(8396d55)FieldEmbedConfig(..., processing_location: str | None = None), such as"us", sets where the model processes your documents and queries.- Values depend on the model and your plan; unset means the model's default.
- Set at index creation, typed or as a dict (
embed={"model": ..., "processing_location": "us"}). Like the rest ofembed, it cannot change later. pc.indexes.describe(name).schema.fields["body"].embed.processing_locationreports it; 10.2.0 dropped it.- Dense
embedonly;FieldSparseEmbedConfigdoes not take it.
from pinecone import FieldEmbedConfig, Pinecone, SchemaBuilder pc = Pinecone() schema = ( SchemaBuilder() .add_string_field( "body", embed=FieldEmbedConfig(model="text-embedding-3-large", processing_location="us"), ) .build() ) pc.indexes.create(name="support-articles-us", schema=schema)Search guide organized by kind of search (docs only) (Search documents, d6e79e1)
- The guide starts from the kind of search you want, semantic, sparse-vector or full-text, and names the clause for each, split by whether Pinecone embeds the query or you pass a vector. Declare a schema and upsert documents builds its two example indexes.
# Clauses available before 10.3.0; the guide maps each to a kind of search. from pinecone import DenseVectorQuery, EmbedQuery, SparseEmbedQuery, SparseValues, SparseVectorQuery, TextQuery # Semantic: by meaning EmbedQuery(field="body", query="how did Rome move water") # Pinecone embeds the text DenseVectorQuery(field="body_vector", values=[0.012, -0.087, 0.153]) # you pass the vector # Sparse-vector: by weighted term overlap SparseEmbedQuery(field="body", query="roman aqueduct") SparseVectorQuery(field="body_sparse_vector", sparse_values=SparseValues(indices=[3, 41], values=[0.6, 0.4])) # Full-text: by the words themselves TextQuery(fields=["title"], query="roman - v10.2.0Release v10.2.02026-10-23 · 2026-10-23 18:51 UTC
查看更新说明
Version 10.2.0 fixes a TLS certificate-verification flaw in the gRPC client and adds full-text match operators to the
Fieldfilter builder. It targets the same2026-07API as 10.1.0 and removes or renames nothing.What to do:
- Upgrade to 10.2.0 if you use the gRPC client.
- Whichever client you use, upgrade
certifito 2026.10.19 or later.
Security
gRPC users: upgrade to 10.2.0 (RUSTSEC-2026-0382, CVE-2026-111943, 7ecd4b0)
- Affected: 9.0.0 through 10.1.0, if your code uses
pc.index(..., grpc=True),PineconeGRPC, orGrpcIndex/GRPCIndex. - Risk: the bundled
rustls-webpkican accept certificates chained through emSign intermediates whose private keys are now public. An attacker with those keys and a position on your network path could impersonate your index and read your API key and data. - Fix: 10.2.0 bundles
rustls-webpki0.103.16, which rejects those chains.
Everyone, gRPC users included: upgrade
certifi(GHSA-6q48-6c7w-9gw2)- Affected: all control-plane and data plane REST calls, which go through httpx and trust whichever
certifiis installed in your environment. - Risk:
certifireleases before 2026.10.19 trust the same compromised emSign roots. - Why upgrading
pineconeisn't enough: the SDK deliberately doesn't pincertifi, so it stays compatible with the other packages in your environment. - Action: run
pip install --upgrade "certifi>=2026.10.19"(oruv add "certifi>=2026.10.19") and keep that floor in your own dependencies. - Custom CA bundles: if you pass
ssl_ca_certsor setSSL_CERT_FILEorSSL_CERT_DIR, make sure that bundle no longer trusts the emSign roots.
No action needed for
tokio: the bundledtokiomoves to 1.51.6 for RUSTSEC-2026-0386. The SDK never calls the affected API.What's new
Full-text match filters for documents (docs, 9fc62f4)
Narrow document search and fetch results by the words in a text field, not only by exact values.
Fieldgains three methods:match_phrase: the words, in ordermatch_all: every word, in any ordermatch_any: at least one of the words
Things to know:
- Fields: they work on
stringfields declared withfull_text_search, or withembed/sparse_embedunless you setstore_text=False. - Methods: use them in the
filterofdocuments.searchanddocuments.fetch. The server rejects them indocuments.deleteanddocuments.update. - Usage: as with every
Fieldfilter, pass the result's.to_dict().
from pinecone import EmbedQuery, Field, Pinecone pc = Pinecone() index = pc.index("articles") # "body" is a string field declared with embed=True # Semantic search, limited to documents whose body contains "roman aqueduct" # and whose year metadata is 100 or later. results = index.documents.search( namespace="en", top_k=5, score_by=[EmbedQuery(field="body", query="how did Rome move water")], filter=(Field("body").match_phrase("roman aqueduct") & Field("year").gte(100)).to_dict(), )Fixes
index.create_namespace(name="__default__")still raises "reserved and cannot be created", but the message no longer claims the namespace always exists. It now explains that this holds only on an index created withdimension/metric, and that on a document index you create it by upserting documents into it. (bbe1282)
Docs
New guides for document indexes:
- v10.1.0Release v10.1.02026-10-20 · 2026-10-20 17:43 UTC
查看更新说明
Version 10.1.0 lets a document index embed text for you. It targets the same
2026-07API as 10.0.0 and removes or renames nothing.What's new
-
Pinecone can embed your text: mark a
stringfieldembed=Trueorsparse_embed=True. (docs, f32f4e2)from pinecone import EmbedQuery, Pinecone, SchemaBuilder # Reads the API key from the PINECONE_API_KEY environment variable. pc = Pinecone() # Declare a string field that Pinecone embeds for you. schema = SchemaBuilder().add_string_field("body", embed=True).build() pc.indexes.create(name="articles", schema=schema) index = pc.index("articles") # Write plain-text documents; Pinecone embeds each body. index.documents.upsert( namespace="en", documents=[ {"_id": "a1", "body": "Aqueducts carried water by gravity"}, {"_id": "a2", "body": "The Colosseum seated 50,000 people"}, {"_id": "a3", "body": "Hypocausts heated the public baths"}, {"_id": "a4", "body": "Roman roads were built in layers"}, ], ) # Search with plain text; Pinecone embeds the query too. results = index.documents.search( namespace="en", top_k=2, score_by=[ EmbedQuery(field="body", query="how did Rome move water"), ], ) for doc in results.matches: print(doc.id, doc.score)- Send at most 96 documents per upsert or update; the default
batch_upsertsize of 50 fits. - An
EmbedQueryorSparseEmbedQuerymust be the only clause inscore_by. - Choose the model with
FieldEmbedConfigorFieldSparseEmbedConfig; skip storing text withstore_text=False. - Responses report embedding tokens in
usage.embed_total_tokens. (6ff91fd)
- Send at most 96 documents per upsert or update; the default
-
documents.batch_upsertsplits a batch the server rejects as too large, instead of failing it. (8f1f96c) -
documents.fetchtakes alimitof up to 10,000 for filtered fetches. (6ea0da1) -
HTTP 413 raises
PayloadTooLargeError, a subclass ofApiError. (445d520) -
Python 3.15 is supported, with prebuilt wheels. (04e7125)
Behavior changes
These are subtle changes that clarify or fix how the SDK handles error cases and invalid input. For a working integration the real-world impact should be minimal. The 10.0 to 10.1 upgrade docs shows before and after for each.
Calls that succeeded on 10.0.0
- To wait for a write, poll
documents.search, notdocuments.fetch; only search reportsis_reconciled. (recipe, 203cf92) - Unknown keys in a dict
score_byclause raisePineconeValueError; deleting them leaves results unchanged. (70a44c5) - Some
ValueErrors are nowPineconeTypeError; catchPineconeErrororTypeError. (481b7f9) - Documents methods need a dict
filter=; call.to_dict()on a filter-builderCondition. (01a6ef3) - A plain-
http://i
-
- v10.0.0Release v10.0.02026-09-03 · 2026-09-03 14:49 UTC
查看更新说明
Version 10.0.0 is the SDK for the Pinecone
2026-07API. It runs on Python 3.10 through 3.14 and sends2026-07on every plane by default. The release graduates the schema-based document interface,SchemaBuilder, and the rest of the2026-07API out ofpinecone.previewonto the main client objects. There are breaking changes: a short list of the most important changes are outlined below, and Migrating to V10 is the complete accounting.If your workload upserts and queries an existing index, upgrading does not change what your code means.
upsert,query,fetch,update,delete,list, anddescribe_index_statstake the same arguments and return the same shapes they did on 9.x;pc.Index("movies")andpc.index("movies")both still hand you an index, though onlypc.index()narrows its return type, so reachindex.documentsthrough that one; and none of those operations is deprecated or scheduled for removal. Indexes you created before2026-07go on being served by them. Three things do change on that path, each covered below: a batchedupsertpaces itself differently, some invalid calls now raise locally instead of being refused by the server, and gRPCupsert_from_dataframecollects partial failures rather than raising on the first one.The breaking changes are concentrated in
pc.indexes.create's arguments and return model, and in the surfaces that graduated out ofpinecone.preview. Flatcreate_index(...)withdimension=,metric=, orspec=needs no edits: it takes its 9.1.0 parameters in the 9.1.0 order, positionally or by keyword. Which family of operations serves an index follows the index itself, not the SDK version — an index created before2026-07is addressed through the vector operations above, and one created with a2026-07document schema throughindex.documents.What's new
Documents API. Records are addressed as documents: a JSON object with an
_id, the fields you declared in the index schema, and any metadata alongside them. Upsert, search, fetch, list, update, and delete all live onindex.documents, on the sync and async clients alike, andindex.documents.batch_upserthandles large loads with the same admission gate and partial-failure reporting the vector path uses. See Quickstart.from pinecone import DenseVectorQuery, Pinecone index = Pinecone().index("quickstart") index.documents.upsert( namespace="movies", documents=[ { "_id": "movie-001", "embedding": [0.1, 0.2, 0.3], "title": "Arrival", }, ], ) results = index.documents.search( namespace="movies", top_k=3, score_by=[DenseVectorQuery(field="embedding", values=[0.1, 0.2, 0.3])], )SchemaBuilder. An index's fields are declared as a schema, and
SchemaBuilderbuilds that schema in Python instead of by hand-assembling nested dicts. Everyadd_*method returns the builder, andbuild()returns a plain{"fields": {...}}dict you hand straight topc.indexes.create(schema=...). See Schema Builder.from pinecone import Pinecone, SchemaBuilder schema = ( SchemaBuilder() .add_dense_vector_field("embedding", dimension=1024, metric="cosine") .add_string_field("title", full_text_search={"language": "en"}) .build() ) pc = Pinecone() pc.indexes.create( name="product-search", schema=schema, deployment={ "deployment_type": "managed", "cloud": "aws", "region": "us-east-1", }, )Full-text search configuration. String fields carry their own full-text search config: language, stemming, stop words, and character n-grams for substring and autocomplete matching, set per field at index creation.
- v9.1.09.1.02026-06-04 · 2026-06-04 13:45 UTC
查看更新说明
Release v9.1.0
v9.1.0 is the retry-resilience release. It overhauls how the SDK behaves under throttling: decorrelated jitter on every transport, plus automatic per-host concurrency back-off that shrinks in-flight bulk requests during a 429 storm and recovers as pressure eases. A new
RateLimitErrorlets callers catch throttling distinctly, and a dedicated retries guide documents the full model. Secondary changes round outGrpcIndexparity with the REST clients and restore the v8search(query={...})request shape.
Highlights
- Decorrelated jitter on every transport. REST (sync and async) and gRPC now use AWS-style decorrelated jitter for retry backoff, so many clients throttled at the same moment no longer retry in lockstep.
- Automatic concurrency back-off under throttling. Bulk operations self-tune downward when the backend rate-limits a host and recover as throttling subsides — an AIMD control loop, per host, with no new knobs to configure.
- Bounded multi-namespace fan-out.
AsyncIndex.query_namespacesno longer fires one unbounded request per namespace — a common cause of self-inflicted 429 storms. It's now capped at 10 in-flight. RateLimitErrorfor HTTP 429. Rate-limit responses raise a dedicatedpinecone.errors.RateLimitError, so you can catch throttling distinctly from other server errors.- New retries guide at
docs/guides/retries.md— defaults, jitter math, the adaptive-concurrency ceiling, and the limits of in-process retries under multi-process / serverless deployment. GrpcIndexparity with the REST clients.query_namespaces,query_namespaces_async,fetch_by_metadata, and the full bulk-import API now exist onGrpcIndex, so switching togrpc=Truefor throughput no longer loses functionality.- Community contribution —
search(query={...})syntax from v8 has been restored. Thanks to @pragnyanramtha, the single-argument request-body form that v9.0.x rejected works again onIndex,AsyncIndex, andGrpcIndex.
Retry & resilience
Decorrelated jitter
REST and gRPC retries now use decorrelated jitter — each delay is drawn from a window that grows with the previous delay, capped at
max_wait. This replaces the previous fixed full-jitter backoff and spreads retries from many clients across time instead of bunching them at the same instant. See the retries guide for the exact formula and defaults.Automatic concurrency back-off
Bulk operations now self-tune their concurrency under throttling. When the backend rate-limits a host (HTTP 429/503, or gRPC
RESOURCE_EXHAUSTED), the SDK reduces the number of in-flight requests it allows to that host, then recovers after a streak of successes — the same AIMD (additive-increase / multiplicative-decrease) approach used by TCP congestion control. It's per host, automatic, and requires no configuration;max_concurrencyremains the ceiling the SDK tunes beneath.RateLimitErrorHTTP 429 responses now raise
RateLimitError, a subclass ofApiError, so throttling can be caught distinctly from other server errors:from pinecone.errors import RateLimitError try: pc.indexes.describe("my-index") except RateLimitError: # back off and retry, or surface to your orchestrator ...Exported from
pinecone.errorsand the top-levelpineconenamespace; aRateLimitExceptionalias matches the existing exception-naming pattern.Observability
The retry and concurrency layers emit namespaced log records with consistent
key=valuefields, so you can diagnose throttling from logs without adding instrumentation:pinecone._internal.http_client— DEBUG on each throttled retry attempt (status, host, attempt N/total, computed delay).pinecone._internal.adaptive— DEBUG on each concurrency adjustment; INFO the first time a host is throttled, with an actionable
用户点评
登录用户的真实使用记录,可按版本和硬件筛选还没有人点评。第一个说出真实体验的人最有价值。
Pinecone Python SDK
The Pinecone Python SDK provides a client for the Pinecone vector database. Use it to create and manage indexes, upsert and query records, and run inference operations from Python.
Requires Python 3.10+.
Upgrading from 9.x? create and configure moved from spec=/dimension= to schema=/deployment=; see the v10 migration guide for the field-by-field mapping.
Installation
pip install pinecone
Quick start
An index declares its fields as a schema. Declaring a schema makes it a document
index: you read and write it through index.documents, and each record is a JSON
document whose fields you named yourself.
from pinecone import DenseVectorQuery, Pinecone
pc = Pinecone(api_key="your-api-key") # or omit and set PINECONE_API_KEY
# Create an index. This blocks until the index is ready.
pc.indexes.create(
name="movie-recommendations",
schema={"fields": {"your_vector": {"type": "dense_vector", "dimension": 3, "metric": "cosine"}}},
deployment={"deployment_type": "managed", "cloud": "aws", "region": "us-east-1"},
)
# Get a data-plane handle for that index
index = pc.index("movie-recommendations")
# Upsert documents. Each one needs an `_id`; every other key is either a field
# you declared in the schema or arbitrary metadata.
index.documents.upsert(
namespace="movies-en",
documents=[
{"_id": "movie-001", "your_vector": [0.1, 0.2, 0.3], "title": "Arrival"},
{"_id": "movie-002", "your_vector": [0.4, 0.5, 0.6], "title": "Interstellar"},
],
)
# Search. `score_by` names the field to compare against.
results = index.documents.search(
namespace="movies-en",
top_k=5,
score_by=[DenseVectorQuery(field="your_vector", values=[0.1, 0.2, 0.3])],
include_fields=["title"],
)
for doc in results.matches:
print(doc.id, doc.score)
Upserts apply asynchronously, so a document may not be visible to the next search immediately.
Indexes created another way use other methods: an index created with the
deprecated top-level dimension=/metric= uses index.upsert / index.query, and
a legacy integrated index (pc.indexes.create_for_model(...)) uses
index.upsert_records / index.search. For new indexes that embed text for you,
give a document index a field with integrated embedding. See the
quickstart and the
documentation.
Async usage
The SDK provides an async client for use with asyncio. Its index() is a
coroutine, and the handle it returns is a context manager:
import asyncio
from pinecone import AsyncPinecone, DenseVectorQuery
async def main():
async with AsyncPinecone(api_key="your-api-key") as pc:
index = await pc.index("movie-recommendations")
async with index:
results = await index.documents.search(
namespace="movies-en",
top_k=5,
score_by=[DenseVectorQuery(field="your_vector", values=[0.1, 0.2, 0.3])],
include_fields=["title"],
)
for doc in results.matches:
print(doc.id, doc.score)
asyncio.run(main())
Configuration
from pinecone import Pinecone
pc = Pinecone(
api_key="your-api-key", # or omit and set PINECONE_API_KEY
timeout=60, # request timeout in seconds; index handles inherit it
)
Setting PINECONE_DEBUG=1 before importing pinecone sets the pinecone logger
to DEBUG. The SDK installs no log handler, so configure one to see the output:
import logging
logging.basicConfig()
Development
Clone the repository and install the dev dependency group with uv, which is what CI does:
uv sync --group dev
uv run pytest tests/unit/ -x -v # tests
uv run mypy --strict pinecone/ # type checking
uv run ruff check --fix # linting
uv run ruff format # formatting
The unit suite must leave the working tree clean: git status is expected to report
no changes after a bare uv run pytest tests/unit. Use tmp_path /
tmp_path_factory if a test genuinely needs a file on disk.
Integration suites that hit a real backend are opt-in because they cost money;
each module documents its own gate. Before any release that touches retry logic, HTTP
transport, the AIMD adaptive-concurrency limiter, or the batch-upsert path, run
tests/integration/test_retry_smoke.py with PINECONE_API_KEY and
PINECONE_RETRY_SMOKE=1 set.
License
Apache-2.0. See LICENSE for details.