Skip to content

tdfs4ds.agent.vector_index

tdfs4ds.agent.vector_index

Chroma-backed vector index for the tdfs4ds business dictionary.

Three collections per feature store mirror the three business dictionary tables: - <prefix>__<store>__objects -> FS_BUSINESS_DICTIONARY_OBJECTS - <prefix>__<store>__sections -> FS_BUSINESS_DICTIONARY_SECTIONS - <prefix>__<store>__columns -> FS_BUSINESS_DICTIONARY_COLUMNS

One set per store (0.3.3.15, see chroma_collection_name): the primary and each read-only store (tdfs4ds.read_stores()) keep their own collections in the same local index, so switching or attaching a store never wipes another one's embeddings, and a search covers every attached store. The collections named tdfs4ds_objects / _sections / _columns (before 0.3.3.15, one set for whichever store was primary) are no longer used.

logger module-attribute

logger = getLogger(__name__)

_COLLECTION_OBJECTS module-attribute

_COLLECTION_OBJECTS = 'tdfs4ds_objects'

_COLLECTION_SECTIONS module-attribute

_COLLECTION_SECTIONS = 'tdfs4ds_sections'

_COLLECTION_COLUMNS module-attribute

_COLLECTION_COLUMNS = 'tdfs4ds_columns'

_VALID_SOURCES module-attribute

_VALID_SOURCES = {'objects', 'sections', 'columns'}

_CHARS_PER_TOKEN module-attribute

_CHARS_PER_TOKEN = 4

_SOURCE_TO_COLLECTION module-attribute

_SOURCE_TO_COLLECTION = {'objects': _COLLECTION_OBJECTS, 'sections': _COLLECTION_SECTIONS, 'columns': _COLLECTION_COLUMNS}

_SOURCES module-attribute

_SOURCES = ('objects', 'sections', 'columns')

_CHROMA_NAME_MAX module-attribute

_CHROMA_NAME_MAX = 63

_LOCAL module-attribute

_LOCAL = local()

_KEYS module-attribute

_KEYS = {'objects': (DOCUMENTATION_BUSINESS_DICTIONARY_OBJECTS, ('DATABASE_NAME', 'OBJECT_NAME'), 'BUSINESS_DESCRIPTION'), 'sections': (DOCUMENTATION_BUSINESS_DICTIONARY_SECTIONS, ('DATABASE_NAME', 'OBJECT_NAME', 'SECTION_NAME'), 'SECTION_CONTENT'), 'columns': (DOCUMENTATION_BUSINESS_DICTIONARY_COLUMNS, ('DATABASE_NAME', 'TABLE_NAME', 'COLUMN_NAME'), 'BUSINESS_DESCRIPTION')}

_STATE_COLLECTION module-attribute

_STATE_COLLECTION = 'tdfs4ds__index_state'

_SOURCE_BUILDERS module-attribute

_SOURCE_BUILDERS = {'objects': _objects_to_docs, 'sections': _sections_to_docs, 'columns': _columns_to_docs}

_EMBED_BATCH_SIZE module-attribute

_EMBED_BATCH_SIZE = 8

_GET_CHUNK module-attribute

_GET_CHUNK = 500

_MODEL_KEY module-attribute

_MODEL_KEY = 'embedding_model'

get_embeddings

get_embeddings() -> Embeddings

Return a LangChain Embeddings instance based on the active provider.

Resolution order for each setting: - EMBEDDING_MODEL_PROVIDER -> falls back to INSTRUCT_MODEL_PROVIDER - EMBEDDING_MODEL_API_KEY -> falls back to INSTRUCT_MODEL_API_KEY - EMBEDDING_MODEL_URL -> falls back to INSTRUCT_MODEL_URL - EMBEDDING_MODEL_MODEL -> used as-is (default: text-embedding-3-small)

Injects tdfs4ds config variables into environment so that boto3, Azure, and Google Cloud clients pick up credentials and endpoints automatically.

Returns:

Name Type Description
Embeddings Embeddings

A configured LangChain embedding model.

Raises:

Type Description
ValueError

If the resolved provider is not supported.

_truncate_text

_truncate_text(text: str) -> str

Truncate text to stay within the embedding model's token limit.

Respects tdfs4ds.EMBEDDING_MODEL_MAX_TOKENS (default 450) to prevent "Input validation error: inputs must have less than 512 tokens" from TEI servers.

_resolve_store

_resolve_store(store=None) -> dict

A store descriptor {schema, schema_view, vector_prefix, is_primary}.

store is None (the primary), a database name, or a descriptor dict. A name matching an attached store (table or view database, case-insensitive) gets that store's descriptor; any other name is read as a store that is not attached (Maintenance can index one before it is attached).

_slug

_slug(text: str) -> str

chroma_collection_name

chroma_collection_name(source: str, store=None) -> str

The Chroma collection of source (objects / sections / columns) for store.

<vector_prefix>__<database>__<source>, the database being the store's table database, lowercased. A name Chroma cannot take as it is (a character outside [a-z0-9_-], or too long) is shortened and followed by a hash of the database name, so two stores never share a collection. Teradata names are case-insensitive, so DB_LAB and db_lab are the same store.

_get_chroma_store

_get_chroma_store(collection_name: str)

Return a LangChain Chroma vector store for the given collection.

Parameters:

Name Type Description Default
collection_name str

Name of the Chroma collection.

required

Returns:

Name Type Description
Chroma

A configured LangChain Chroma vector store.

_execute

_execute(query: str) -> list

Rows of query: through this thread's own connection when it has one, else through teradataml (the historical path).

can_use_own_connection

can_use_own_connection() -> bool

True when a raw connection can be opened from the TDFS4DS_TD_* settings.

own_connection

own_connection()

Give this thread its own raw teradatasql connection for the index reads.

Opened from the TDFS4DS_TD_* settings (utils.reconnect); closed on exit. When none can be opened, reads go through teradataml as before and the reason is logged. Yields the connection or None.

_store_view_query

_store_view_query(store: dict, view: str, columns: str, where: str = '') -> str

Read a store that is not the primary through its public business-dictionary view: read rights are enough, and the view already applies CURRENT VALIDTIME and drops blank descriptions.

_since_sql

_since_sql(since, first: bool) -> str

WHERE|AND ValidStart >= TIMESTAMP '<since>+00:00' ('' when since is None).

since is a UTC YYYY-MM-DD HH:MM:SS read from the database (_db_now_utc), never the client's clock.

_fetch_objects

_fetch_objects(store: Optional[dict] = None, since=None) -> pd.DataFrame

Fetch all rows from the business dictionary objects table.

Uses execute_sql because CURRENT VALIDTIME must be at the outermost level. A store other than the primary is read through its public view. since: only rows documented at or after that UTC time (primary only).

_fetch_sections

_fetch_sections(store: Optional[dict] = None, since=None) -> pd.DataFrame

Fetch all rows from the business dictionary sections table.

_fetch_columns

_fetch_columns(store: Optional[dict] = None, since=None) -> pd.DataFrame

Fetch all rows from the business dictionary columns table.

_current_ids

_current_ids(source: str) -> set

Ids of the primary's documented rows of source now, without their text (the same ids and the same blank-text rule as the _<source>_to_docs).

_db_now_utc

_db_now_utc()

The database's current time in UTC, YYYY-MM-DD HH:MM:SS (None if unreadable).

The indexing date compares with the documentation's ValidStart, written by the database: a client clock would drift from it.

_state_id

_state_id(store: dict, source: str) -> str

read_index_state

read_index_state(store=None) -> dict

{source: {'indexed_at', 'embedding_model', 'documents'}} of store (empty when never recorded). Read-only: never creates anything.

_write_index_state

_write_index_state(store: dict, source: str, indexed_at: str, documents: int) -> None

index_freshness

index_freshness(store=None) -> dict

Is store's Chroma index behind its documentation? No embedding, no Chroma scan.

Per source: indexed_at (UTC, the database's time when the last build started), changed = documented rows written since (ValidStart at or after it), and state:

  • 'up_to_date' / 'behind' - from the dates;
  • 'never' - no build recorded;
  • 'model_changed' - built with another embedding model (everything re-embeds);
  • 'unknown' - a read-only store: its public views carry no ValidStart, so only a full comparison (the next build) can tell.

A row removed from the documentation is not counted (it ends a period, it does not open one); the next build drops it from the index.

_objects_to_docs

_objects_to_docs(df: DataFrame) -> tuple[list[Document], list[str]]

_sections_to_docs

_sections_to_docs(df: DataFrame) -> tuple[list[Document], list[str]]

_columns_to_docs

_columns_to_docs(df: DataFrame) -> tuple[list[Document], list[str]]

_embed_batch_size

_embed_batch_size() -> int

_embedding_model_id

_embedding_model_id() -> str

_expected_entries

_expected_entries(docs: list, ids: list[str]) -> tuple[dict, dict]

(texts, metadatas) keyed by id, exactly as a build would store them.

classify_stored

classify_stored(collection, ids: list[str], texts: dict, metadatas: dict) -> dict

{id: 'indexed' | 'stale' | 'missing'} for each expected id.

The single comparison behind both the build (which skips 'indexed' rows) and the admin app's index status: stored with the same text, metadata and embedding model = 'indexed'; stored differently = 'stale'; absent = 'missing'. collection is a raw chromadb collection. Raises on a read error -- callers decide whether to fail open.

_unchanged_ids

_unchanged_ids(store, ids: list[str], texts: dict, metadatas: dict) -> set

Ids already stored with the same text, metadata and embedding model.

Fail-open: any error reading the collection returns an empty set, i.e. everything is (re-)embedded exactly as before this optimisation existed.

_open_chroma_collection_readonly

_open_chroma_collection_readonly(collection_name: str)

The raw chromadb collection, or None when it does not exist.

For status reads: unlike _get_chroma_store it never creates the collection and never builds an embedding client (reading needs neither, and a status page must work while the embedding model is unconfigured). Not strictly read-only on disk: opening a PersistentClient updates chroma.sqlite3 (chromadb's own housekeeping, observed live), though no collection or row is written.

_raw_chroma_client

_raw_chroma_client()

A raw chromadb client on the configured index (no embedding client).

chroma_index_status

chroma_index_status(source: str, df: DataFrame, store=None) -> dict

Index status of the business-dictionary rows in df for one Chroma collection.

df has the columns the _fetch_<source> helpers return. The expected documents come from the same builders as build_vector_index (ids, truncation, metadata, embedding model), so a row reported 'indexed' is one the next build would skip. Returns {'collection', 'exists', 'rows': {id: status}, 'orphans': [ids stored but no longer expected], 'count'}. Raises on a read error. store: see chroma_collection_name (None = the primary).

chroma_store_status

chroma_store_status(store=None) -> dict

What the local Chroma index holds for store, without reading the database.

{'store', 'collections': {source: {'name', 'exists', 'count'}}, 'documents'}. Never creates a collection and needs no embedding model. A collection that cannot be read reports exists=None with the error, whole.

_upsert_documents_batched

_upsert_documents_batched(store: Chroma, docs: list[Document], ids: list[str], progress=None) -> tuple

Upsert documents into a Chroma store in batches (add new, update existing).

Rows already stored with the same text, metadata and embedding model are skipped -- re-embedding them would produce the same vector, and on a large business dictionary that is most of the cost of a routine rebuild.

Respects tdfs4ds.EMBEDDING_BATCH_SIZE and the inter-batch delay tdfs4ds.EMBEDDING_BATCH_DELAY (for vLLM/TEI overload prevention); the delay is applied between batches, not after the final batch. An expired embedding credential is offered for renewal and the current batch retried (see tdfs4ds.utils.credential_renewal).

progress, when given, is called as progress(done, total) once before the first batch and after each one (total = documents to embed). A failing callback never stops the build.

Returns (n_embedded, n_skipped).

build_vector_index

build_vector_index(force_rebuild: bool = False, progress=None, stores=None)

Build or refresh the three vector-store collections from the business dictionary tables.

Dispatches to the configured backend (tdfs4ds.VECTOR_STORE_BACKEND): 'chroma' (default) or 'teradata'.

On Chroma, each feature store has its own three collections (chroma_collection_name). stores lists the stores to index (database names or descriptors; default: every store in tdfs4ds.read_stores(), the primary first). A store that is not the primary is read through its public FS_V_BUSINESS_DICTIONARY_* views, so read rights are enough, and nothing is written to its database. stores is ignored by the Teradata backend, which indexes the primary only.

progress, when given, is called with one dict per step: store, source, collection (1-based), n_collections, done, total (documents to embed in that collection, None before it is known) and detail. A failing callback never stops the build.

Returns, on Chroma, {'stores': [{'store', 'collections': {source: {'embedded', 'skipped', 'error'}}}]}.

Parameters:

Name Type Description Default
force_rebuild bool

If True, delete existing collections and re-index from scratch. On Chroma this needs no special privileges. On Teradata it destroys and recreates each collection, which requires admin privileges (Collection.destroy() is admin-only) — when the destroy is refused the call falls back to the ordinary refresh path with a warning rather than failing. (Before 0.3.1.167 this flag was a no-op on the Teradata backend.) If False: on Chroma, embed only rows that are missing or changed (same text, metadata and embedding model = skipped); on Teradata, refresh an existing collection with update(data_refresh=True), falling back to destroy + recreate, and create a missing one (since 0.3.1.169; see vector_store_teradata.build_teradata_index).

False

_count

_count(store) -> int

_remove_orphans

_remove_orphans(store, expected_ids) -> int

Delete from the collection the ids no longer documented; their number.

Fail-open (0): a read error never stops a build. The ids compared are the ones the build itself writes, so nothing else in the collection is touched.

search_vector_index

search_vector_index(query: str, sources: list[str] = ('objects', 'sections', 'columns'), section_names: Optional[List[str]] = None, top_k: int = 10, k: Optional[int] = None) -> pd.DataFrame

Search the requested Chroma collections using similarity search.

Parameters:

Name Type Description Default
query str

Natural language search query.

required
sources list[str]

Which collections to search (subset of 'objects', 'sections', 'columns').

('objects', 'sections', 'columns')
section_names Optional[List[str]]

If provided and 'sections' is in sources, filter by SECTION_NAME.

None
top_k int

Number of results per collection.

10
k Optional[int]

Alias for top_k — accepted because k is the near-universal convention in the surrounding ecosystem (Chroma, FAISS, LangChain retrievers), unlike tdfs4ds's own top_k naming. If both are given and differ, k wins and a warning is logged.

None

Returns:

Type Description
DataFrame

DataFrame with columns: SOURCE, OBJECT_NAME, SECTION_NAME, COLUMN_NAME, TEXT, SCORE.