/fix change model to gpt 5.4 mini

#17
by rhbt6767 - opened
DEV_PLAN.md CHANGED
@@ -222,6 +222,7 @@ Status legend: ⬜ not started · 🔄 in progress · ✅ done · ⛔ blocked ·
222
  | 26 | **Charts (DEFERRED):** store Plotly JSON in a future `chart` table (not matplotlib PNG) | — | 🔎 | **Landed 2026-07-13 (pr/16, §0.6 V1–V3):** `render_chart` + `message_charts` + `GET /api/v1/charts`, Plotly JSON as decided. 🔎 pending the dedorch DDL run (V5) + live e2e |
223
  | 27 | **Images (DEFERRED):** image table (id, analysis_id, msg/report ref, order) + originals in a bucket | — | ⏸️ | Maintenance-heavy; parked |
224
  | 28 | **UI research** (FE): new-analysis form, knowledge menu (user vs analysis level), report artifacts + version selector | Team | ⬜ new | No dedicated UI person; interview + old analysis UI removed |
 
225
 
226
  ## 5. Critical path & sequencing
227
 
 
222
  | 26 | **Charts (DEFERRED):** store Plotly JSON in a future `chart` table (not matplotlib PNG) | — | 🔎 | **Landed 2026-07-13 (pr/16, §0.6 V1–V3):** `render_chart` + `message_charts` + `GET /api/v1/charts`, Plotly JSON as decided. 🔎 pending the dedorch DDL run (V5) + live e2e |
223
  | 27 | **Images (DEFERRED):** image table (id, analysis_id, msg/report ref, order) + originals in a bucket | — | ⏸️ | Maintenance-heavy; parked |
224
  | 28 | **UI research** (FE): new-analysis form, knowledge menu (user vs analysis level), report artifacts + version selector | Team | ⬜ new | No dedicated UI person; interview + old analysis UI removed |
225
+ | 29 | **LLM env quad rename `__4o` → `__54m`** + set the four `azureai__*__54m` secrets on the HF Space | Rifqi | 🔄 | Code done 2026-07-14 (pr/17): settings quad + 9 call sites + 2 eval runners renamed; deployment is `gpt-5.4-mini`. Suite **381 passed, 2 failed (both pre-existing), 7 skipped** — same as baseline; ruff clean on touched files; `import main` 0. **Hard rename — no `__4o` fallback**, so HF fails loudly on the first LLM call until the four `__54m` secrets are set. Root cause it fixes: HF silently ran GPT-4o while local ran 5.4-mini → same question, same catalog, planner hallucinated catalog ids on HF only. **Action: set HF secrets, redeploy, re-run the failing question.** Local `.env` still carries the now-dead `__4o` keys — safe to delete |
226
 
227
  ## 5. Critical path & sequencing
228
 
REPO_STATUS.md CHANGED
@@ -2,7 +2,7 @@
2
 
3
  **Audience:** teammates onboarding onto the Python repo (`Agentic-Service-Data-Eyond-Catalog`).
4
  **Scope:** what the code does **right now** (branch `pr/4`, ticket KM-652). Describes current state only — no roadmap or to-dos.
5
- **Snapshot date:** 2026-06-25. **Data-layer reconcile 2026-07-01:** §8/§12 updated — dedorch cutover done, `data_catalog` model reconciled. **Query-path fix 2026-07-02:** §8/§13 — dedorch catalogs ship no FKs → Python infers them (`fk_inference.py`); shared-Fernet-key gotcha documented. **Agent-quality fixes 2026-07-08 (pr/13):** from the scoped live-test review — the planner gains an explicit **infeasible** outcome (`TaskList.infeasible_reason` → deterministic EN/ID data-gap reply via `refusals.data_gap_message`; no more force-mapping absent measures like `pa` AS "revenue"), the IR validator rejects bare selects under `group_by` (self-corrects via the planner retry), `analyze_trend` handles integer year/month columns (was collapsing every row into one 1970-01 bucket), planner few-shots add top-N (Example G) + infeasible (Example H), numeric catalog `sample_values` are base64-decoded at read (`catalog/sample_decode.py` — stopgap for Go's byte-marshaling; primary fix is Go-side), traceability no longer emits null source rows for failed retrievals, and `check_data` hides `-1` row counts. **Report v2 + analyze_merge planner support 2026-07-09 (pr/13):** Sofia's `analyze_merge` tool (8abf635, KM-703) is now planner-supported (`_validate_data_source` guards `data_right`, two-retrieve→merge few-shot Example I, planner.md "Two measures per entity" rule); the report gains per-business-question answers (`bq_answers` — drafted by the SAME single LLM call, index-based record refs, deterministic fallback unchanged), "Attempted, Unresolved" + "Excluded Analyses" sections (failed runs are no longer silently dropped), evidence tables copied from `results_snapshot` (table-kind outputs, ≤3/record ≤10 rows ≤8 cols, `check_*` skipped), normalized caveat dedupe with caps (12/10), and single-language output via `detect_reply_language`; the report surface adds `GET /tools/report/{analysis_id}/records` (curation list), `GET …/readiness` (FE delta guard), and `exclude_record_ids` on POST — see API_CONTRACT_BE_PYTHON.md. **Report compaction 2026-07-09 (pr/13):** the rendered markdown drops the "Notes & Limitations", "Attempted, Unresolved", and "How This Was Analyzed" sections (team decision — compact report; render blocks commented out in `report/generator.py`, not deleted). The JSON body keeps `caveats`/`open_questions`/`unresolved`/`method_steps` and the curation/records endpoints are unchanged. **Traceability `data_used` layer 2026-07-13 (pr/15):** `GET /api/v1/traceability` gains a resolved, user-facing `data_used[]` block (one per `retrieve_data` call) — real source/table/column names, joins, plain-language filters, and result columns split into read-from-data vs `computed` (with `formula`, e.g. `total_revenue` = `SUM(line_total)`, so an alias is never shown as a real column). Ids are kept but **machine-only (FE must not render)**. Also adds `tool_calls[].summary`, and `sources[]` now carry `source_name` + every table touched. Deterministic catalog resolution (new `src/traceability/resolve.py`), no LLM, never-throw; catalog threaded to the scratchpad at the slow-path composition root. Additive/non-breaking; contract + `TRACEABILITY_FE_HANDOFF.md` updated. **Spine v2 W2+W1 2026-07-13 (pr/16):** §6/§7/§8/§9/§12 — `render_chart` tool lands (first of the `render_*` family: deterministic Plotly-JSON `dataeyond.chart.v1` envelope, hand-built, **no plotly dependency**; planner-selected only on an explicit chart ask, EN/ID) + Python-owned `message_charts` store + `GET /api/v1/charts` (FE fetches on `done`, same pattern as traceability; empty list = valid 200); planner gains a named **recipe table** + viz few-shots (Example J tail, Example K viz-infeasible) + validator Check 10 (`render_chart.data` must reference a table-producing task); and the slow path gains the **S1a quality checkpoint** (`slow_path/checkpoint.py`, 0 LLM, never-throw, between runner and assembler: CK1 all-failed → deterministic honest-failure answer with **no** assembler call, CK2 empty retrieve + downstream, CK3 10k-cap truncation, CK4 single trend bucket, CK5 all-null column, CK6 chart-spec sanity; flags render as an "Execution assessment" block in the assembler input and every flag logs `repair_candidate` — the S1b evidence base). Design + handoff doc: `SPINE_V2_PLAN.md`. **Cross-repo update 2026-06-29:** §2/§8/§11/§12 re-verified against
6
  the **Go source** (`Orchestrator-Agent-Service`), not its docs. The Go service has moved well past its
7
  own (uncommitted, stale) design docs: it now hosts the **dedorch SQL migrations** in-repo and a full
8
  **`/api/v1/analyses` + `/api/v1/skills`** REST surface. Go does **not** call Python yet — those skills
@@ -44,7 +44,7 @@ streaming.
44
 
45
  | Repo | Role | We edit? |
46
  |---|---|---|
47
- | **Python** — `Agentic-Service-Data-Eyond-Catalog` (this repo) | The agentic LLM service: router, gate, skills, slow analytical path, structured query engine, unstructured RAG, report generation, analysis-session state. FastAPI + async SQLAlchemy + LangChain + Azure GPT-4o. | **Yes — the only repo we edit.** |
48
  | **Go** — `Orchestrator-Agent-Service` | Gateway / data plane: auth/JWT, documents (Azure Blob + CSV/XLSX→Parquet + embeddings), database_clients (Fernet creds), **catalog ingestion** (moved into Go, KM-578/590), **all dedorch SQL migrations** (now embedded in the Go repo: `internal/repository/postgres/migrations/0001–0004`), and the **full analysis-lifecycle REST surface** (`/api/v1/analyses` CRUD + messages + reports, `/api/v1/skills`). The **interview agent and chat-rooms are deprecated → HTTP 410** (`internal/api/deprecation.go`). | Reference only. |
49
  | **FE** — `E2E-Frontend-Data-Eyond` | React/Vite SPA. Talks to Go for everything and to Python only for chat streaming. | Reference only. |
50
 
@@ -60,7 +60,7 @@ Shared infra: **Postgres** (app tables + `data_catalog` jsonb + PGVector `langch
60
 
61
  - Python 3.12, FastAPI, uvicorn, sse-starlette
62
  - Async SQLAlchemy 2.0 + asyncpg (Postgres); psycopg3 for the PGVector engine
63
- - LangChain + langchain-openai (Azure OpenAI GPT-4o) + langchain-postgres (PGVector)
64
  - Redis (response + retrieval cache), Azure Blob (uploads + Parquet)
65
  - pandas / pyarrow, sqlglot, pydantic v2, structlog, slowapi, langfuse
66
  - DB connectors: psycopg2, pymysql, pymssql, sqlalchemy-bigquery, snowflake-sqlalchemy
@@ -88,7 +88,7 @@ POST /chat/stream { user_id, room_id, message }
88
  ├─ greeting/farewell short-circuit (_fast_intent, EN+ID) ── hit → canned reply
89
  ├─ load last-10 history
90
  └─ ChatHandler.handle:
91
- 1. classify → RouterDecision [1 GPT-4o call]
92
  2. ensure analysis-state row (get-or-create, idempotent)
93
  3. emit `intent` (internal; gates caching), then dispatch:
94
  chat → ChatbotAgent → SSE
@@ -218,7 +218,7 @@ Joins are single-level equi-joins to a related table **in the same source**, FK-
218
  ## 9. Subsystems (where the code lives)
219
 
220
  ### Router — `src/agents/orchestration.py`
221
- One GPT-4o structured-output call → `RouterDecision{intent, rewritten_query, confidence}`,
222
  `intent ∈ {chat, help, check, unstructured_flow, structured_flow}` (`problem_statement` removed
223
  2026-06-25). It's a
224
  *handler* classifier: `structured_flow` = slow path, `unstructured_flow` = fast RAG; the
@@ -391,8 +391,13 @@ records-based report; floor: ≥1 `analyze_*` success). Wiring Go → Python is
391
  because PGVector emits multi-statement strings asyncpg rejects.
392
  - **Identifiers vs values:** identifiers come from the catalog and are inlined as quoted; filter
393
  values are always parameterized.
394
- - **Settings aliases:** `.env` uses double-underscore names (`azureai__api_key__4o`); `Settings`
395
- exposes them as `azureai_api_key_4o`.
 
 
 
 
 
396
  - **Shared Fernet key across repos (gotcha).** User DB credentials in `databases` are written +
397
  encrypted by **Go** and decrypted by Python; both read the **same** env var
398
  `dataeyond__db__credential__key` (Go: `configs/app.yaml` → `credentials.fernet_key`). The two
 
2
 
3
  **Audience:** teammates onboarding onto the Python repo (`Agentic-Service-Data-Eyond-Catalog`).
4
  **Scope:** what the code does **right now** (branch `pr/4`, ticket KM-652). Describes current state only — no roadmap or to-dos.
5
+ **Snapshot date:** 2026-06-25. **Data-layer reconcile 2026-07-01:** §8/§12 updated — dedorch cutover done, `data_catalog` model reconciled. **Query-path fix 2026-07-02:** §8/§13 — dedorch catalogs ship no FKs → Python infers them (`fk_inference.py`); shared-Fernet-key gotcha documented. **Agent-quality fixes 2026-07-08 (pr/13):** from the scoped live-test review — the planner gains an explicit **infeasible** outcome (`TaskList.infeasible_reason` → deterministic EN/ID data-gap reply via `refusals.data_gap_message`; no more force-mapping absent measures like `pa` AS "revenue"), the IR validator rejects bare selects under `group_by` (self-corrects via the planner retry), `analyze_trend` handles integer year/month columns (was collapsing every row into one 1970-01 bucket), planner few-shots add top-N (Example G) + infeasible (Example H), numeric catalog `sample_values` are base64-decoded at read (`catalog/sample_decode.py` — stopgap for Go's byte-marshaling; primary fix is Go-side), traceability no longer emits null source rows for failed retrievals, and `check_data` hides `-1` row counts. **Report v2 + analyze_merge planner support 2026-07-09 (pr/13):** Sofia's `analyze_merge` tool (8abf635, KM-703) is now planner-supported (`_validate_data_source` guards `data_right`, two-retrieve→merge few-shot Example I, planner.md "Two measures per entity" rule); the report gains per-business-question answers (`bq_answers` — drafted by the SAME single LLM call, index-based record refs, deterministic fallback unchanged), "Attempted, Unresolved" + "Excluded Analyses" sections (failed runs are no longer silently dropped), evidence tables copied from `results_snapshot` (table-kind outputs, ≤3/record ≤10 rows ≤8 cols, `check_*` skipped), normalized caveat dedupe with caps (12/10), and single-language output via `detect_reply_language`; the report surface adds `GET /tools/report/{analysis_id}/records` (curation list), `GET …/readiness` (FE delta guard), and `exclude_record_ids` on POST — see API_CONTRACT_BE_PYTHON.md. **Report compaction 2026-07-09 (pr/13):** the rendered markdown drops the "Notes & Limitations", "Attempted, Unresolved", and "How This Was Analyzed" sections (team decision — compact report; render blocks commented out in `report/generator.py`, not deleted). The JSON body keeps `caveats`/`open_questions`/`unresolved`/`method_steps` and the curation/records endpoints are unchanged. **Traceability `data_used` layer 2026-07-13 (pr/15):** `GET /api/v1/traceability` gains a resolved, user-facing `data_used[]` block (one per `retrieve_data` call) — real source/table/column names, joins, plain-language filters, and result columns split into read-from-data vs `computed` (with `formula`, e.g. `total_revenue` = `SUM(line_total)`, so an alias is never shown as a real column). Ids are kept but **machine-only (FE must not render)**. Also adds `tool_calls[].summary`, and `sources[]` now carry `source_name` + every table touched. Deterministic catalog resolution (new `src/traceability/resolve.py`), no LLM, never-throw; catalog threaded to the scratchpad at the slow-path composition root. Additive/non-breaking; contract + `TRACEABILITY_FE_HANDOFF.md` updated. **Spine v2 W2+W1 2026-07-13 (pr/16):** §6/§7/§8/§9/§12 — `render_chart` tool lands (first of the `render_*` family: deterministic Plotly-JSON `dataeyond.chart.v1` envelope, hand-built, **no plotly dependency**; planner-selected only on an explicit chart ask, EN/ID) + Python-owned `message_charts` store + `GET /api/v1/charts` (FE fetches on `done`, same pattern as traceability; empty list = valid 200); planner gains a named **recipe table** + viz few-shots (Example J tail, Example K viz-infeasible) + validator Check 10 (`render_chart.data` must reference a table-producing task); and the slow path gains the **S1a quality checkpoint** (`slow_path/checkpoint.py`, 0 LLM, never-throw, between runner and assembler: CK1 all-failed → deterministic honest-failure answer with **no** assembler call, CK2 empty retrieve + downstream, CK3 10k-cap truncation, CK4 single trend bucket, CK5 all-null column, CK6 chart-spec sanity; flags render as an "Execution assessment" block in the assembler input and every flag logs `repair_candidate` — the S1b evidence base). Design + handoff doc: `SPINE_V2_PLAN.md`. **LLM model + env rename 2026-07-14 (pr/17):** §2/§3/§9/§13 — the generation LLM is now **Azure GPT-5.4-mini** (deployment `gpt-5.4-mini`), not GPT-4o, and the settings quad is renamed `azureai__*__4o` → **`azureai__*__54m`** across all 9 LLM call sites. **Hard rename, no `__4o` fallback** — an environment that still sets only `__4o` resolves to empty strings and fails on the first LLM call, by design: the silent-wrong-model drift is exactly how HF stayed on GPT-4o while local ran 5.4-mini (identical question, identical catalog, divergent planner output — HF hallucinated catalog ids, local planned correctly). Deploying requires all four `__54m` vars set in the HF Space secrets. **Cross-repo update 2026-06-29:** §2/§8/§11/§12 re-verified against
6
  the **Go source** (`Orchestrator-Agent-Service`), not its docs. The Go service has moved well past its
7
  own (uncommitted, stale) design docs: it now hosts the **dedorch SQL migrations** in-repo and a full
8
  **`/api/v1/analyses` + `/api/v1/skills`** REST surface. Go does **not** call Python yet — those skills
 
44
 
45
  | Repo | Role | We edit? |
46
  |---|---|---|
47
+ | **Python** — `Agentic-Service-Data-Eyond-Catalog` (this repo) | The agentic LLM service: router, gate, skills, slow analytical path, structured query engine, unstructured RAG, report generation, analysis-session state. FastAPI + async SQLAlchemy + LangChain + Azure GPT-5.4-mini (was GPT-4o until 2026-07-14). | **Yes — the only repo we edit.** |
48
  | **Go** — `Orchestrator-Agent-Service` | Gateway / data plane: auth/JWT, documents (Azure Blob + CSV/XLSX→Parquet + embeddings), database_clients (Fernet creds), **catalog ingestion** (moved into Go, KM-578/590), **all dedorch SQL migrations** (now embedded in the Go repo: `internal/repository/postgres/migrations/0001–0004`), and the **full analysis-lifecycle REST surface** (`/api/v1/analyses` CRUD + messages + reports, `/api/v1/skills`). The **interview agent and chat-rooms are deprecated → HTTP 410** (`internal/api/deprecation.go`). | Reference only. |
49
  | **FE** — `E2E-Frontend-Data-Eyond` | React/Vite SPA. Talks to Go for everything and to Python only for chat streaming. | Reference only. |
50
 
 
60
 
61
  - Python 3.12, FastAPI, uvicorn, sse-starlette
62
  - Async SQLAlchemy 2.0 + asyncpg (Postgres); psycopg3 for the PGVector engine
63
+ - LangChain + langchain-openai (Azure OpenAI **GPT-5.4-mini**, deployment `gpt-5.4-mini`; env quad `azureai__*__54m` — renamed from `__4o` 2026-07-14) + langchain-postgres (PGVector)
64
  - Redis (response + retrieval cache), Azure Blob (uploads + Parquet)
65
  - pandas / pyarrow, sqlglot, pydantic v2, structlog, slowapi, langfuse
66
  - DB connectors: psycopg2, pymysql, pymssql, sqlalchemy-bigquery, snowflake-sqlalchemy
 
88
  ├─ greeting/farewell short-circuit (_fast_intent, EN+ID) ── hit → canned reply
89
  ├─ load last-10 history
90
  └─ ChatHandler.handle:
91
+ 1. classify → RouterDecision [1 LLM call]
92
  2. ensure analysis-state row (get-or-create, idempotent)
93
  3. emit `intent` (internal; gates caching), then dispatch:
94
  chat → ChatbotAgent → SSE
 
218
  ## 9. Subsystems (where the code lives)
219
 
220
  ### Router — `src/agents/orchestration.py`
221
+ One structured-output LLM call (GPT-5.4-mini) → `RouterDecision{intent, rewritten_query, confidence}`,
222
  `intent ∈ {chat, help, check, unstructured_flow, structured_flow}` (`problem_statement` removed
223
  2026-06-25). It's a
224
  *handler* classifier: `structured_flow` = slow path, `unstructured_flow` = fast RAG; the
 
391
  because PGVector emits multi-statement strings asyncpg rejects.
392
  - **Identifiers vs values:** identifiers come from the catalog and are inlined as quoted; filter
393
  values are always parameterized.
394
+ - **Settings aliases:** `.env` uses double-underscore names (`azureai__api_key__54m`); `Settings`
395
+ exposes them as `azureai_api_key_54m`.
396
+ - **LLM env quad renamed `__4o` → `__54m` (2026-07-14).** The generation LLM is GPT-5.4-mini; the
397
+ four vars are `azureai__api_key__54m`, `azureai__endpoint__url__54m`,
398
+ `azureai__deployment__name__54m`, `azureai__api__version__54m`. Hard rename — no `__4o` fallback,
399
+ so an environment missing the new names fails loudly instead of silently serving a different model
400
+ (which is exactly how HF drifted onto 4o while local ran 5.4-mini).
401
  - **Shared Fernet key across repos (gotcha).** User DB credentials in `databases` are written +
402
  encrypted by **Go** and decrypted by Python; both read the **same** env var
403
  `dataeyond__db__credential__key` (Go: `configs/app.yaml` → `credentials.fernet_key`). The two
eval/help/run_eval.py CHANGED
@@ -347,7 +347,7 @@ def _model_name() -> str:
347
  try:
348
  from src.config.settings import settings
349
 
350
- return str(settings.azureai_deployment_name_4o)
351
  except Exception: # noqa: BLE001 — meta only; .env may be absent
352
  return "gpt-4o"
353
 
 
347
  try:
348
  from src.config.settings import settings
349
 
350
+ return str(settings.azureai_deployment_name_54m)
351
  except Exception: # noqa: BLE001 — meta only; .env may be absent
352
  return "gpt-4o"
353
 
eval/intent/run_eval.py CHANGED
@@ -345,7 +345,7 @@ def _model_name() -> str:
345
  try:
346
  from src.config.settings import settings
347
 
348
- return str(settings.azureai_deployment_name_4o)
349
  except Exception: # noqa: BLE001 — meta only; .env may be absent
350
  return "gpt-4o"
351
 
 
345
  try:
346
  from src.config.settings import settings
347
 
348
+ return str(settings.azureai_deployment_name_54m)
349
  except Exception: # noqa: BLE001 — meta only; .env may be absent
350
  return "gpt-4o"
351
 
src/agents/chatbot.py CHANGED
@@ -115,10 +115,10 @@ def _build_default_chain() -> Runnable:
115
  from src.config.settings import settings
116
 
117
  llm = AzureChatOpenAI(
118
- azure_deployment=settings.azureai_deployment_name_4o,
119
- openai_api_version=settings.azureai_api_version_4o,
120
- azure_endpoint=settings.azureai_endpoint_url_4o,
121
- api_key=settings.azureai_api_key_4o,
122
  temperature=0.3,
123
  # Emit token usage on the final streamed chunk (this agent only streams), so
124
  # the fast-path answer reports tokens to Langfuse like the non-streaming calls.
 
115
  from src.config.settings import settings
116
 
117
  llm = AzureChatOpenAI(
118
+ azure_deployment=settings.azureai_deployment_name_54m,
119
+ openai_api_version=settings.azureai_api_version_54m,
120
+ azure_endpoint=settings.azureai_endpoint_url_54m,
121
+ api_key=settings.azureai_api_key_54m,
122
  temperature=0.3,
123
  # Emit token usage on the final streamed chunk (this agent only streams), so
124
  # the fast-path answer reports tokens to Langfuse like the non-streaming calls.
src/agents/guard.py CHANGED
@@ -89,10 +89,10 @@ def _build_default_chain() -> Runnable:
89
  from src.config.settings import settings
90
 
91
  llm = AzureChatOpenAI(
92
- azure_deployment=settings.azureai_deployment_name_4o,
93
- openai_api_version=settings.azureai_api_version_4o,
94
- azure_endpoint=settings.azureai_endpoint_url_4o,
95
- api_key=settings.azureai_api_key_4o,
96
  temperature=0,
97
  )
98
  prompt = ChatPromptTemplate.from_messages(
 
89
  from src.config.settings import settings
90
 
91
  llm = AzureChatOpenAI(
92
+ azure_deployment=settings.azureai_deployment_name_54m,
93
+ openai_api_version=settings.azureai_api_version_54m,
94
+ azure_endpoint=settings.azureai_endpoint_url_54m,
95
+ api_key=settings.azureai_api_key_54m,
96
  temperature=0,
97
  )
98
  prompt = ChatPromptTemplate.from_messages(
src/agents/handlers/help.py CHANGED
@@ -151,10 +151,10 @@ def _build_default_chain() -> Runnable:
151
  from src.config.settings import settings
152
 
153
  llm = AzureChatOpenAI(
154
- azure_deployment=settings.azureai_deployment_name_4o,
155
- openai_api_version=settings.azureai_api_version_4o,
156
- azure_endpoint=settings.azureai_endpoint_url_4o,
157
- api_key=settings.azureai_api_key_4o,
158
  temperature=0.3,
159
  model_kwargs={"stream_options": {"include_usage": True}},
160
  )
 
151
  from src.config.settings import settings
152
 
153
  llm = AzureChatOpenAI(
154
+ azure_deployment=settings.azureai_deployment_name_54m,
155
+ openai_api_version=settings.azureai_api_version_54m,
156
+ azure_endpoint=settings.azureai_endpoint_url_54m,
157
+ api_key=settings.azureai_api_key_54m,
158
  temperature=0.3,
159
  model_kwargs={"stream_options": {"include_usage": True}},
160
  )
src/agents/handlers/problem_statement.py CHANGED
@@ -88,10 +88,10 @@ def _build_default_chain() -> Runnable:
88
  from src.config.settings import settings
89
 
90
  llm = AzureChatOpenAI(
91
- azure_deployment=settings.azureai_deployment_name_4o,
92
- openai_api_version=settings.azureai_api_version_4o,
93
- azure_endpoint=settings.azureai_endpoint_url_4o,
94
- api_key=settings.azureai_api_key_4o,
95
  temperature=0,
96
  )
97
  prompt = ChatPromptTemplate.from_messages(
 
88
  from src.config.settings import settings
89
 
90
  llm = AzureChatOpenAI(
91
+ azure_deployment=settings.azureai_deployment_name_54m,
92
+ openai_api_version=settings.azureai_api_version_54m,
93
+ azure_endpoint=settings.azureai_endpoint_url_54m,
94
+ api_key=settings.azureai_api_key_54m,
95
  temperature=0,
96
  )
97
  prompt = ChatPromptTemplate.from_messages(
src/agents/orchestration.py CHANGED
@@ -85,10 +85,10 @@ def _build_default_chain() -> Runnable:
85
  from src.config.settings import settings
86
 
87
  llm = AzureChatOpenAI(
88
- azure_deployment=settings.azureai_deployment_name_4o,
89
- openai_api_version=settings.azureai_api_version_4o,
90
- azure_endpoint=settings.azureai_endpoint_url_4o,
91
- api_key=settings.azureai_api_key_4o,
92
  temperature=0,
93
  )
94
  prompt = ChatPromptTemplate.from_messages(
 
85
  from src.config.settings import settings
86
 
87
  llm = AzureChatOpenAI(
88
+ azure_deployment=settings.azureai_deployment_name_54m,
89
+ openai_api_version=settings.azureai_api_version_54m,
90
+ azure_endpoint=settings.azureai_endpoint_url_54m,
91
+ api_key=settings.azureai_api_key_54m,
92
  temperature=0,
93
  )
94
  prompt = ChatPromptTemplate.from_messages(
src/agents/planner/service.py CHANGED
@@ -48,10 +48,10 @@ def _build_default_chain() -> Runnable:
48
  from src.config.settings import settings
49
 
50
  llm = AzureChatOpenAI(
51
- azure_deployment=settings.azureai_deployment_name_4o,
52
- openai_api_version=settings.azureai_api_version_4o,
53
- azure_endpoint=settings.azureai_endpoint_url_4o,
54
- api_key=settings.azureai_api_key_4o,
55
  temperature=0,
56
  )
57
  prompt = ChatPromptTemplate.from_messages(
 
48
  from src.config.settings import settings
49
 
50
  llm = AzureChatOpenAI(
51
+ azure_deployment=settings.azureai_deployment_name_54m,
52
+ openai_api_version=settings.azureai_api_version_54m,
53
+ azure_endpoint=settings.azureai_endpoint_url_54m,
54
+ api_key=settings.azureai_api_key_54m,
55
  temperature=0,
56
  )
57
  prompt = ChatPromptTemplate.from_messages(
src/agents/report/generator.py CHANGED
@@ -89,10 +89,10 @@ def _build_default_chain() -> Runnable:
89
  from src.config.settings import settings
90
 
91
  llm = AzureChatOpenAI(
92
- azure_deployment=settings.azureai_deployment_name_4o,
93
- openai_api_version=settings.azureai_api_version_4o,
94
- azure_endpoint=settings.azureai_endpoint_url_4o,
95
- api_key=settings.azureai_api_key_4o,
96
  temperature=0,
97
  )
98
  prompt = ChatPromptTemplate.from_messages(
 
89
  from src.config.settings import settings
90
 
91
  llm = AzureChatOpenAI(
92
+ azure_deployment=settings.azureai_deployment_name_54m,
93
+ openai_api_version=settings.azureai_api_version_54m,
94
+ azure_endpoint=settings.azureai_endpoint_url_54m,
95
+ api_key=settings.azureai_api_key_54m,
96
  temperature=0,
97
  )
98
  prompt = ChatPromptTemplate.from_messages(
src/agents/slow_path/assembler.py CHANGED
@@ -54,10 +54,10 @@ def _build_default_chain() -> Runnable:
54
  from src.config.settings import settings
55
 
56
  llm = AzureChatOpenAI(
57
- azure_deployment=settings.azureai_deployment_name_4o,
58
- openai_api_version=settings.azureai_api_version_4o,
59
- azure_endpoint=settings.azureai_endpoint_url_4o,
60
- api_key=settings.azureai_api_key_4o,
61
  temperature=0,
62
  )
63
  prompt = ChatPromptTemplate.from_messages(
 
54
  from src.config.settings import settings
55
 
56
  llm = AzureChatOpenAI(
57
+ azure_deployment=settings.azureai_deployment_name_54m,
58
+ openai_api_version=settings.azureai_api_version_54m,
59
+ azure_endpoint=settings.azureai_endpoint_url_54m,
60
+ api_key=settings.azureai_api_key_54m,
61
  temperature=0,
62
  )
63
  prompt = ChatPromptTemplate.from_messages(
src/config/settings.py CHANGED
@@ -41,11 +41,11 @@ class Settings(BaseSettings):
41
  redis_url: str
42
  redis_prefix: str = "dataeyond-agent-service_"
43
 
44
- # Azure OpenAI - GPT-4o (map to .env names with double underscores)
45
- azureai_api_key_4o: str = Field(alias="azureai__api_key__4o", default="")
46
- azureai_endpoint_url_4o: str = Field(alias="azureai__endpoint__url__4o", default="")
47
- azureai_deployment_name_4o: str = Field(alias="azureai__deployment__name__4o", default="")
48
- azureai_api_version_4o: str = Field(alias="azureai__api__version__4o", default="")
49
 
50
  # Azure OpenAI - Embeddings
51
  azureai_api_key_embedding: str = Field(alias="azureai__api_key__embedding", default="")
 
41
  redis_url: str
42
  redis_prefix: str = "dataeyond-agent-service_"
43
 
44
+ # Azure OpenAI - GPT-5.4-mini (map to .env names with double underscores)
45
+ azureai_api_key_54m: str = Field(alias="azureai__api_key__54m", default="")
46
+ azureai_endpoint_url_54m: str = Field(alias="azureai__endpoint__url__54m", default="")
47
+ azureai_deployment_name_54m: str = Field(alias="azureai__deployment__name__54m", default="")
48
+ azureai_api_version_54m: str = Field(alias="azureai__api__version__54m", default="")
49
 
50
  # Azure OpenAI - Embeddings
51
  azureai_api_key_embedding: str = Field(alias="azureai__api_key__embedding", default="")
src/query/planner/service.py CHANGED
@@ -40,10 +40,10 @@ def _build_default_chain() -> Runnable:
40
  from src.config.settings import settings
41
 
42
  llm = AzureChatOpenAI(
43
- azure_deployment=settings.azureai_deployment_name_4o,
44
- openai_api_version=settings.azureai_api_version_4o,
45
- azure_endpoint=settings.azureai_endpoint_url_4o,
46
- api_key=settings.azureai_api_key_4o,
47
  temperature=0,
48
  )
49
  prompt = ChatPromptTemplate.from_messages(
 
40
  from src.config.settings import settings
41
 
42
  llm = AzureChatOpenAI(
43
+ azure_deployment=settings.azureai_deployment_name_54m,
44
+ openai_api_version=settings.azureai_api_version_54m,
45
+ azure_endpoint=settings.azureai_endpoint_url_54m,
46
+ api_key=settings.azureai_api_key_54m,
47
  temperature=0,
48
  )
49
  prompt = ChatPromptTemplate.from_messages(