tdfs4ds.configure¶
tdfs4ds.configure
¶
Interactive, non-destructive configuration of tdfs4ds.
:func:configure_interactively walks through the settings that make the
AI-facing half of tdfs4ds work -- the database connection, the instruct model,
the embedding model and the vector store -- and records the answers in an
existing .env line by line.
How it differs from :func:tdfs4ds.generate_ai_studio_env:
- That one is specific to Teradata AI Studio and rewrites the whole file.
This one works anywhere and goes through :func:
tdfs4ds.patch_dotenv, so comments, ordering, commented-out alternatives and variables it knows nothing about survive. Only values that actually changed are touched. - Variables already present in the file are the defaults of the questions;
Enter keeps them. A secret is shown as
set (hidden, N chars).
Principles, each one learned the hard way elsewhere in this package:
- Ask the endpoint, do not make the user type a model name. Models are
listed with the provider's own mechanism -- HTTP
/modelsfor the OpenAI-compatible family,boto3for Bedrock (foundation models and inference profiles, because many models can only be invoked through a profile id). - A key is asked for only when it is needed. Cloud roles, profiles and keyless gateways work without one, so the wizard first tries without and asks only when the provider answers with an authentication failure.
- A backend that cannot work is not written. The Teradata Vector Store may be missing, unlicensed or unreachable; that is detected and local Chroma is offered instead.
- Checks describe the file, not the session. They run through
:class:
tdfs4ds.ai_studio._Staged, which clears managed variables the file does not set. - Secrets are written only after an explicit yes, in a separate
patch_dotenv(..., allow_secrets=True)call, and never printed.
Nothing here runs at import time.
PROVIDERS
module-attribute
¶
PROVIDERS = ('openai', 'openai-compatible', 'vllm', 'litellm', 'azure', 'bedrock', 'aws', 'gcp', 'mistralai')
_HTTP_PROVIDERS
module-attribute
¶
_PROVIDER_FIELDS
module-attribute
¶
_PROVIDER_FIELDS = {'openai': (('URL', 'API base URL (Enter for api.openai.com)', False),), 'openai-compatible': (('URL', 'API base URL', True),), 'vllm': (('URL', 'API base URL', True),), 'mistralai': (('URL', 'API base URL (Enter for the default)', False),), 'litellm': (('URL', 'LiteLLM proxy URL (Enter to use provider env vars)', False),), 'azure': (('URL', 'Azure endpoint, https://<name>.openai.azure.com/', True), ('AZURE_DEPLOYMENT', 'deployment name (Enter = model name)', False), ('AZURE_API_VERSION', 'API version', False)), 'bedrock': (('REGION', 'AWS region, e.g. us-east-1', True),), 'aws': (('REGION', 'AWS region, e.g. us-east-1', True),), 'gcp': (('GCP_PROJECT', 'GCP project id', True), ('GCP_LOCATION', 'GCP location', False))}
_GENERIC_NO_IDENTITY
module-attribute
¶
_GENERIC_NO_IDENTITY = ('unauthorized', 'invalid api key', 'incorrect api key', 'invalid_api_key', 'authentication', 'api_key client option must be set')
_STATUS
module-attribute
¶
_FOREIGN_ENV
module-attribute
¶
_FOREIGN_ENV = ('AWS_BEARER_TOKEN_BEDROCK', 'AWS_DEFAULT_REGION', 'AWS_REGION', 'AZURE_OPENAI_API_KEY', 'AZURE_OPENAI_ENDPOINT', 'OPENAI_API_VERSION', 'GOOGLE_CLOUD_PROJECT', 'CLOUD_ML_REGION')
_VS_AUTH_ATTRS
module-attribute
¶
_VS_AUTH_ATTRS = ('VECTOR_STORE_AUTH_BASE_URL', 'VECTOR_STORE_AUTH_USERNAME', 'VECTOR_STORE_AUTH_PASSWORD', 'VECTOR_STORE_AUTH_AUTH_TOKEN', 'VECTOR_STORE_AUTH_PAT_TOKEN', 'VECTOR_STORE_AUTH_PEM_FILE')
_Ctx
¶
Bases: object
What is in the file, what the user has changed, what was found.
_stage
¶
_is_placeholder
¶
True when value is a generator placeholder rather than a real value.
_is_secret
¶
True when attr names a credential that must never be written in clear.
_parse_dotenv
¶
Parse path as a .env file and return a {ATTR: raw_value} dict
for every TDFS4DS_* variable found.
Handles:
- KEY=VALUE
- KEY="VALUE" / KEY='VALUE'
- export KEY=VALUE
- # comments (whole-line and trailing) and blank lines
Trailing-comment rule, matching python-dotenv so a file behaves the same
whichever loader reads it: in an unquoted value, whitespace followed by
# starts a comment and is dropped. A # with no whitespace before it
is part of the value (PASSWORD=abc#def is abc#def), and quoting
keeps everything verbatim (PASSWORD="abc #def") — which is how to
write a value that genuinely contains " #".
This used to keep the comment: PASSWORD=secret # prod became the
literal secret # prod, which then failed authentication somewhere far
away from the file that caused it.
patch_dotenv
¶
Set individual TDFS4DS_* variables in an existing .env, in place.
:func:export_config and :func:tdfs4ds.generate_ai_studio_env both
rewrite the whole file, which loses its comments, its ordering and the
commented-out alternatives they deliberately put there. This changes one
line at a time, so a probed value can be recorded into a file a human
maintains.
It is line-based rather than parse-and-rewrite because :func:_parse_dotenv
is lossy for this purpose — it drops comments, ordering and quoting, so it
cannot serve as the read side of a read-modify-write.
Which line is changed, and why:
- The last uncommented occurrence.
_parse_dotenvassigns as it reads, so on a duplicate the last one is what takes effect; patching any other would leave the file saying one thing and meaning another. - Otherwise the first commented-out slot (
#TDFS4DS_X=) is uncommented in place. A generated file offers such slots precisely so that turning one on is an edit. - Otherwise appended, preceded by comment if given.
A commented slot is never uncommented while a live line exists — a
generated file carries commented alternatives next to the live choice
(two MCP_SERVER_URL lines, for instance), and enabling one of those
would silently switch the setting to the alternative.
Parameters¶
path : str or Path
An existing .env. Creating one is :func:export_config's or
:func:tdfs4ds.generate_ai_studio_env's job, not this function's, so a
missing file raises rather than being conjured half-populated.
updates : dict
{'STRUCTURED_OUTPUT_METHOD': 'function_calling'} — keys with or
without the TDFS4DS_ prefix. Values are rendered the way
:func:_coerce reads them back, so None is written as the literal
None (which loads as None), not as an empty line.
comment : str, optional
Provenance note, written as a trailing comment on the line itself.
Say where the value came from and when: a pinned setting that was right
in one session is wrong in another, and a stale pin should be visible
rather than silent.
Trailing rather than above, because the whole line is rewritten on each
call — so re-pinning replaces the note instead of stacking a new one on
every run. It is dropped for a value that has to be quoted: the parser
takes a quoted value verbatim, so a trailing comment would become part
of it. Newlines are folded to "; " for the same reason.
allow_secrets : bool, default False
Required to write a credential. A general-purpose file patcher must not
be the thing that puts a password into a file someone later commits, so
by default a name :func:_is_secret recognises is refused.
Returns¶
dict
{'updated': [...], 'added': [...], 'unchanged': [...]} of full
TDFS4DS_* names. Nothing is written when everything is unchanged.
Raises¶
ValueError path does not exist, a key is not a registered variable (it would only earn an "unknown .env variable" warning on load), or it is a credential without allow_secrets.
_is_missing_credentials
¶
True when nothing authenticated the call: a key (or a role) is missing.
_is_not_permitted
¶
True when the caller is known but this action or model is refused.
_needs_key
¶
Should the wizard ask for an API key because of this error?
Yes for a missing identity. For a refusal: no when the provider's identity is an environment role (Bedrock, Vertex) -- it was recognised and denied, a key is not the answer -- and, for a keyless HTTP gateway, only when no key is held yet (a bare 403 there usually means "send one").
_full_error
¶
The whole error, cause chain included. Never the first line only: the half that names the fault is often the later one.
_ask_text
¶
Ask for a plain value; the file's value is the default.
_ask_secret
¶
Ask for a secret. Enter keeps the one already set; it is never echoed.
_choose
¶
Pick from options by number or name; anything else keeps default.
_run_check
¶
Run one diagnostics._check_* live, against the effective config.
_bedrock_inference_profiles
¶
Inference-profile ids. Many on-demand models (Claude, Nova) can only be
invoked through a profile id such as us.anthropic.<model>, never through
the bare foundation-model id, so listing foundation models alone would
offer ids that fail at the first call.
_list_model_ids
¶
Models the configured provider serves: (ids, error_text_or_None).
Uses the package's own listing code (list_instruct_models /
list_embedding_models) so the proxy and TLS settings apply, and adds
Bedrock inference profiles for instruct models. Any failure is returned,
in full, for the caller to show -- never raised.
_pick_model
¶
Choose from the models the endpoint serves; the file's value leads.
_provider_for
¶
The provider in force for kind (embedding falls back to instruct).
_ensure_key
¶
Ask for an API key after the provider rejected a keyless attempt.
_provider_settings
¶
Provider, then only the fields that provider needs.
_bedrock_transport
¶
Converse (the default) or Bedrock's OpenAI-compatible endpoint, and how that endpoint authenticates: an API key, or the environment's role.
_keyless_extra
¶
For the OpenAI-compatible family a client cannot be built without a key, so the keyless attempt carries the conventional placeholder.
_type_models
¶
Type the model, or several candidates to try (comma-separated).
The list was unavailable, so the call is the only judge of what works.
Candidates are probed with one real call each; the first that answers wins
(or the user chooses among several). A model id, an inference-profile id
(eu./us./apac. prefix) and an ARN are all accepted.
_profile_variants
¶
Inference-profile spellings of a bare Bedrock model id, region first.
_probe_candidates
¶
Try each candidate with a live call; return the one to use.
_teradata_vector_store
¶
Configure and verify the Teradata Vector Store. True when it works.
configure_interactively
¶
configure_interactively(path='.env', *, sections=SECTIONS, check=True, write_secrets='ask', prompt=True)
Configure tdfs4ds by answering questions; update path in place.
Existing TDFS4DS_* lines are the defaults and are edited in place, so
comments, ordering and unrelated variables survive. A missing file is
created. Only values that changed are written.
Parameters¶
path : str or Path, default '.env'
The file to update.
sections : iterable of str
Any of 'connection', 'instruct', 'embedding',
'vector_store'. Default: all, in that order.
check : bool, default True
Run the live checks (model call, vector-store service). With False
only the questions are asked and model lists are not fetched.
write_secrets : {'ask', 'never', 'always'}, default 'ask'
Whether API keys, passwords and tokens may be written to the file.
'ask' asks once, with the default answer no.
prompt : bool, default True
False (or no terminal) asks nothing and writes nothing.
Returns¶
dict
{'path', 'updated', 'added', 'unchanged', 'skipped', 'checks'}
-- variable names and statuses only, never a value.
_skip_checks
¶
check=False: ask the plain questions, fetch and call nothing.