diff --git a/agent_framework_oci/MULTI_ITEM_FRAMEWORK_FIX_20260918.md b/agent_framework_oci/MULTI_ITEM_FRAMEWORK_FIX_20260918.md new file mode 100644 index 00000000..0f8e4376 --- /dev/null +++ b/agent_framework_oci/MULTI_ITEM_FRAMEWORK_FIX_20260918.md @@ -0,0 +1,29 @@ +# Multi-item result preservation fix + +## Objective +Preserve the terminal outcome of each item executed by the primary transactional tool. A failure in a later auxiliary/composite step must not erase successful item outcomes or turn an already-completed multi-item operation into a total failure. + +## Framework-only change +No agent/template business logic is required for this fix. The runtime now recognizes an explicit structural contract on the requested tool: a `results` array with two or more entries carrying boolean `success` or `ok` fields. + +For workflow-backed tools the authoritative source is preferentially: + +`workflow.output[tool_name].results` + +The framework derives one of: +- `SUCCESS` +- `PARTIAL_SUCCESS` +- `FAILED` + +and publishes a generic `metadata.multi_item` summary with item counts. + +When one or more primary items completed successfully but the outer wrapper is `ok=false` because a later auxiliary/post-processing step failed, the normalized result preserves the original failure as `original_ok=false` / `secondary_error` while exposing the requested operation as operationally successful (`ok=true`). + +The LLM context also receives an explicit generic instruction that successful per-item terminal evidence cannot be overwritten by a secondary error and that mixed outcomes must be reported individually. + +## Regression tests +Added `tests/test_multi_item_result_normalization.py` covering: +- 2 success + 1 failure -> `PARTIAL_SUCCESS`; +- all primary items successful + later secondary failure -> primary `SUCCESS` preserved; +- single-item behavior unchanged; +- unrelated nested tool results cannot override failure of the requested primary tool. diff --git a/agent_framework_oci/Tuning-Performance/Authentication/agent_template_backend_authentication/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Authentication/agent_template_backend_authentication/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Authentication/agent_template_backend_authentication/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Authentication/agent_template_backend_authentication/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Deterministic_Transactional_Workflow/agent_template_backend/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/llm_profiles.yaml index bebfcf1f..06996e27 100644 --- a/agent_framework_oci/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/External_Guardrails_Judges/agent_template_backend/llm_profiles.yaml @@ -9,11 +9,18 @@ profiles: model: openai.gpt-4.1 temperature: 0 max_tokens: 700 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 + router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Long_Term_Memory/templates/agent_template_backend/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend/llm_profiles.yaml index bebfcf1f..06996e27 100644 --- a/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend/llm_profiles.yaml @@ -9,11 +9,18 @@ profiles: model: openai.gpt-4.1 temperature: 0 max_tokens: 700 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 + router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Normal/templates/agent_template_backend_day_zero/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Route_Stickness/templates/agent_template_backend_day_zero/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Transaction_Evidence/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Transaction_Evidence/agent_template_backend/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Transaction_Evidence/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Transaction_Evidence/agent_template_backend/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/Tuning-Performance/Transaction_Pre_Validation/agent_template_backend/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/docs/FIX_LLM_MAX_TOKENS_CONFIGURATION_20260918.md b/agent_framework_oci/docs/FIX_LLM_MAX_TOKENS_CONFIGURATION_20260918.md new file mode 100644 index 00000000..6521abb5 --- /dev/null +++ b/agent_framework_oci/docs/FIX_LLM_MAX_TOKENS_CONFIGURATION_20260918.md @@ -0,0 +1,58 @@ +# Correção — `max_tokens` por `llm_profiles.yaml` / `.env` + +## Objetivo + +Remover `max_tokens` efetivos fixados nos pontos de inferência do framework sem perder compatibilidade com os budgets anteriores. + +A precedência usada pelos pontos corrigidos passa a ser: + +1. `max_tokens` do profile selecionado em `llm_profiles.yaml`; +2. `max_tokens` do profile `default` do mesmo YAML, quando aplicável ao resolver; +3. `LLM_MAX_TOKENS` configurado no ambiente / `.env`; +4. valor legado do ponto de inferência, usado somente como fallback de compatibilidade. + +O parâmetro interno `fallback_max_tokens` **não é uma nova configuração do usuário**. Ele apenas preserva o valor histórico quando não existe configuração externa. + +## Pontos corrigidos + +- Enterprise Router: + - transaction parameter relevance: fallback legado `256`; + - transaction intent shift: fallback legado `512`; + - multi-intent: fallback legado `768`; + - routing normal: fallback legado `512`. +- MCP parameter extraction: fallback `80`. +- Processing interruption classifier: fallback `8`. +- LLM guardrail: fallback `600`. +- RAG query rewrite: fallback `300`. +- RAG context compression: mantém a fórmula histórica `max(512, max_chars // 3)` apenas como fallback. +- Conversation summary memory: mantém a fórmula histórica `max(256, max_summary_chars // 4)` apenas como fallback. + +## Atualização de `llm_profiles.yaml` + +Como os quatro pontos do Enterprise Router usam o mesmo profile `router`, o profile foi ajustado para o **maior budget histórico**, conforme solicitado: + +```yaml +router: + max_tokens: 768 +``` + +Também foram garantidos os profiles explícitos: + +```yaml +processing_interruption_classifier: + max_tokens: 8 + +mcp_parameter_extraction: + max_tokens: 80 +``` + +Os profiles já existentes foram mantidos: + +- `guardrail: 600` +- `rag_rewriter: 300` +- `rag_compressor: 1200` +- `summary_memory: 1200` + +## Compatibilidade + +Se `llm_profiles.yaml` não estiver disponível e `LLM_MAX_TOKENS` não estiver definido, cada ponto corrigido continua usando seu budget histórico. Portanto a correção não transforma a ausência de configuração em `2048` apenas por causa do default global de `Settings`. diff --git a/agent_framework_oci/evals/offline/configs/llm_profiles/llm_profiles.yaml b/agent_framework_oci/evals/offline/configs/llm_profiles/llm_profiles.yaml index 7975152c..db997275 100644 --- a/agent_framework_oci/evals/offline/configs/llm_profiles/llm_profiles.yaml +++ b/agent_framework_oci/evals/offline/configs/llm_profiles/llm_profiles.yaml @@ -9,3 +9,11 @@ profiles: model: mock-judge temperature: 0 max_tokens: 300 + + mcp_parameter_extraction: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 80 + timeout_seconds: 5 + diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/channels/interruption.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/channels/interruption.py index 7c6f55db..9151a1f0 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/channels/interruption.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/channels/interruption.py @@ -58,7 +58,7 @@ async def classify_processing_interruption( response = await llm.ainvoke( [{"role": "system", "content": prompt}], temperature=0, - max_tokens=8, + fallback_max_tokens=8, profile_name=profile_name, component_name=profile_name, generation_name=f"llm.{profile_name}", diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/guardrails/llm_rails.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/guardrails/llm_rails.py index 40c3f901..a5851053 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/guardrails/llm_rails.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/guardrails/llm_rails.py @@ -47,7 +47,7 @@ class LLMGuardrailRail(Guardrail): {"role": "user", "content": prompt}, ], temperature=0, - max_tokens=600, + fallback_max_tokens=600, profile_name=self.profile_name, component_name=self.profile_name, generation_name=f"llm.{self.profile_name}", diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/profile_resolver.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/profile_resolver.py index 3372658c..22cda60b 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/profile_resolver.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/profile_resolver.py @@ -2,6 +2,7 @@ from __future__ import annotations import copy import logging +import os import re from pathlib import Path from typing import Any @@ -164,6 +165,66 @@ class LLMProfileResolver: return effective + def resolve_configured_value( + self, + profile_name: str | None, + key: str, + *, + env_var: str | None = None, + fallback: Any = None, + ) -> Any: + """Resolve one configuration value with an explicit compatibility fallback. + + Precedence is intentionally aligned with the framework configuration model: + 1. specific ``llm_profiles.yaml`` profile; + 2. YAML ``default`` profile; + 3. explicitly configured general environment variable; + 4. the caller-provided legacy fallback. + + The last step is important for old inference points that historically had a + local constant. Pydantic's Settings object always has framework defaults, so + checking only ``settings.LLM_MAX_TOKENS`` would make an *unset* environment + indistinguishable from the global default. + """ + selected_name = self.normalize_profile_name(profile_name) + if self.enabled: + specific_profile = self._profiles.get(selected_name) or {} + default_profile = self._profiles.get("default") or {} + if key in specific_profile and specific_profile.get(key) is not None: + return specific_profile.get(key) + if key in default_profile and default_profile.get(key) is not None: + return default_profile.get(key) + + if env_var: + raw = os.getenv(env_var) + if raw is not None and str(raw).strip() != "": + raw = str(raw).strip() + try: + if isinstance(fallback, bool): + return raw.lower() in {"1", "true", "yes", "on"} + if isinstance(fallback, int) and not isinstance(fallback, bool): + return int(raw) + if isinstance(fallback, float): + return float(raw) + except (TypeError, ValueError): + logger.warning( + "Invalid %s=%r for profile=%s key=%s; using legacy fallback=%r", + env_var, raw, selected_name, key, fallback, + ) + return fallback + return raw + + # Also honor a value explicitly supplied when Settings was instantiated + # programmatically, without treating the class default as configuration. + field_name = env_var or "" + fields_set = getattr(self.settings, "model_fields_set", set()) or set() + if field_name and field_name in fields_set: + value = getattr(self.settings, field_name, None) + if value is not None: + return value + + return fallback + def normalize_profile_name(self, profile_name: str | None) -> str: return _canonical_profile_name(profile_name) diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/providers.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/providers.py index ee91acde..e706f28c 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/providers.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/llm/providers.py @@ -370,6 +370,14 @@ class OCICompatibleOpenAIProvider(LLMProvider): profile_name = kwargs.pop("profile_name", None) component_name = kwargs.pop("component_name", None) or kwargs.pop("component", None) or profile_name or "default" generation_name = kwargs.pop("generation_name", None) or f"llm.{component_name}" + fallback_max_tokens = kwargs.pop("fallback_max_tokens", None) + if fallback_max_tokens is not None: + kwargs["max_tokens"] = self.profile_resolver.resolve_configured_value( + profile_name, + "max_tokens", + env_var="LLM_MAX_TOKENS", + fallback=fallback_max_tokens, + ) generation_name, generation_mapping_meta = _normalize_generation_name(self.telemetry, generation_name) effective = self.profile_resolver.resolve(profile_name, **kwargs) provider = str(effective.get("provider") or self.provider_name) diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/memory/summary_memory.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/memory/summary_memory.py index 024571b5..e1688fe3 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/memory/summary_memory.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/memory/summary_memory.py @@ -167,7 +167,7 @@ class ConversationSummaryMemory: summary = await self.llm.ainvoke([ {"role": "system", "content": "Você resume memória conversacional para agentes corporativos."}, {"role": "user", "content": prompt}, - ], max_tokens=max(256, max_summary_chars // 4), temperature=0.1, profile_name="summary_memory", component_name="summary_memory", generation_name="llm.summary_memory") + ], fallback_max_tokens=max(256, max_summary_chars // 4), temperature=0.1, profile_name="summary_memory", component_name="summary_memory", generation_name="llm.summary_memory") summary = (summary or "").strip() if not summary: return self._deterministic_summary(previous_summary=previous_summary, messages=messages, max_chars=max_summary_chars) diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/rag/rag_service.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/rag/rag_service.py index d641fe2c..ea79035f 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/rag/rag_service.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/rag/rag_service.py @@ -84,7 +84,7 @@ class RagService: {'role': 'user', 'content': prompt}, ], temperature=0, - max_tokens=300, + fallback_max_tokens=300, profile_name=profile_name, component_name=profile_name, generation_name=f"llm.{profile_name}", @@ -112,7 +112,7 @@ class RagService: {'role': 'user', 'content': prompt}, ], temperature=0, - max_tokens=max(512, max_chars // 3), + fallback_max_tokens=max(512, max_chars // 3), profile_name=profile_name, component_name=profile_name, generation_name=f"llm.{profile_name}", diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/routing/enterprise_router.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/routing/enterprise_router.py index f6ec8a73..bfb476a9 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/routing/enterprise_router.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/routing/enterprise_router.py @@ -1045,7 +1045,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(payload, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=256, + fallback_max_tokens=256, profile_name="router", component_name="router.transaction_parameter_relevance", generation_name="llm.transaction_parameter_relevance", @@ -1328,7 +1328,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(user, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=512, + fallback_max_tokens=512, profile_name="router", component_name="router", generation_name="llm.transaction_intent_shift", @@ -1674,7 +1674,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(payload, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=768, + fallback_max_tokens=768, profile_name="router", component_name="router.multi_intent", generation_name="llm.router.multi_intent", @@ -1730,7 +1730,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(user, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=512, + fallback_max_tokens=512, profile_name="router", component_name="router", generation_name="llm.router", diff --git a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py index 2ec6be62..c4ee75dc 100644 --- a/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py +++ b/agent_framework_oci/libs/agent_framework/build/lib/agent_framework/runtime/agent_runtime.py @@ -849,7 +849,7 @@ class AgentRuntimeMixin: component_name="mcp_parameter_extraction", generation_name="llm.mcp_parameter_extraction", temperature=0.0, - max_tokens=80, + fallback_max_tokens=80, ) raw = self._llm_response_text(response).strip() payload = parse_json_object(raw) diff --git a/agent_framework_oci/libs/agent_framework/config/llm_profiles.yaml b/agent_framework_oci/libs/agent_framework/config/llm_profiles.yaml index 9e00520e..8eb5129d 100644 --- a/agent_framework_oci/libs/agent_framework/config/llm_profiles.yaml +++ b/agent_framework_oci/libs/agent_framework/config/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 @@ -72,6 +78,13 @@ profiles: provider: oci_openai model: openai.gpt-4.1 temperature: 0.2 + mcp_parameter_extraction: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 80 + timeout_seconds: 5 + transaction_parameter_extraction: provider: oci_openai model: openai.gpt-4.1-mini diff --git a/agent_framework_oci/libs/agent_framework/llm_profiles.yaml.example b/agent_framework_oci/libs/agent_framework/llm_profiles.yaml.example index 3ef6f870..230c72ee 100644 --- a/agent_framework_oci/libs/agent_framework/llm_profiles.yaml.example +++ b/agent_framework_oci/libs/agent_framework/llm_profiles.yaml.example @@ -15,11 +15,18 @@ profiles: temperature: 0 max_tokens: 700 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 + router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 # Safety / evaluation guardrail: @@ -87,3 +94,11 @@ profiles: provider: oci_openai model: openai.gpt-4.1 temperature: 0.2 + + mcp_parameter_extraction: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 80 + timeout_seconds: 5 + diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc index 7292b69c..70d9720f 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/__pycache__/interruption.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/interruption.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/interruption.py index 7c6f55db..9151a1f0 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/interruption.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/channels/interruption.py @@ -58,7 +58,7 @@ async def classify_processing_interruption( response = await llm.ainvoke( [{"role": "system", "content": prompt}], temperature=0, - max_tokens=8, + fallback_max_tokens=8, profile_name=profile_name, component_name=profile_name, generation_name=f"llm.{profile_name}", diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc index 0a7ca946..babe3e4c 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/__pycache__/llm_rails.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/llm_rails.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/llm_rails.py index 5f63af43..b047ca6c 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/llm_rails.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/guardrails/llm_rails.py @@ -49,7 +49,7 @@ class LLMGuardrailRail(Guardrail): {"role": "user", "content": prompt}, ], temperature=0, - max_tokens=600, + fallback_max_tokens=600, profile_name=self.profile_name, component_name=self.profile_name, generation_name=f"llm.{self.profile_name}", diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc index 698ce2e2..4425f211 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/profile_resolver.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc index 864235c0..2ef52d57 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/__pycache__/providers.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/profile_resolver.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/profile_resolver.py index 90ea4e1a..f77f0843 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/profile_resolver.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/profile_resolver.py @@ -2,6 +2,7 @@ from __future__ import annotations import copy import logging +import os import re from pathlib import Path from typing import Any @@ -164,6 +165,66 @@ class LLMProfileResolver: return effective + def resolve_configured_value( + self, + profile_name: str | None, + key: str, + *, + env_var: str | None = None, + fallback: Any = None, + ) -> Any: + """Resolve one configuration value with an explicit compatibility fallback. + + Precedence is intentionally aligned with the framework configuration model: + 1. specific ``llm_profiles.yaml`` profile; + 2. YAML ``default`` profile; + 3. explicitly configured general environment variable; + 4. the caller-provided legacy fallback. + + The last step is important for old inference points that historically had a + local constant. Pydantic's Settings object always has framework defaults, so + checking only ``settings.LLM_MAX_TOKENS`` would make an *unset* environment + indistinguishable from the global default. + """ + selected_name = self.normalize_profile_name(profile_name) + if self.enabled: + specific_profile = self._profiles.get(selected_name) or {} + default_profile = self._profiles.get("default") or {} + if key in specific_profile and specific_profile.get(key) is not None: + return specific_profile.get(key) + if key in default_profile and default_profile.get(key) is not None: + return default_profile.get(key) + + if env_var: + raw = os.getenv(env_var) + if raw is not None and str(raw).strip() != "": + raw = str(raw).strip() + try: + if isinstance(fallback, bool): + return raw.lower() in {"1", "true", "yes", "on"} + if isinstance(fallback, int) and not isinstance(fallback, bool): + return int(raw) + if isinstance(fallback, float): + return float(raw) + except (TypeError, ValueError): + logger.warning( + "Invalid %s=%r for profile=%s key=%s; using legacy fallback=%r", + env_var, raw, selected_name, key, fallback, + ) + return fallback + return raw + + # Also honor a value explicitly supplied when Settings was instantiated + # programmatically, without treating the class default as configuration. + field_name = env_var or "" + fields_set = getattr(self.settings, "model_fields_set", set()) or set() + if field_name and field_name in fields_set: + value = getattr(self.settings, field_name, None) + if value is not None: + return value + + return fallback + def normalize_profile_name(self, profile_name: str | None) -> str: return _canonical_profile_name(profile_name) diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/providers.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/providers.py index b20c298a..eb15700f 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/providers.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/llm/providers.py @@ -370,6 +370,14 @@ class OCICompatibleOpenAIProvider(LLMProvider): profile_name = kwargs.pop("profile_name", None) component_name = kwargs.pop("component_name", None) or kwargs.pop("component", None) or profile_name or "default" generation_name = kwargs.pop("generation_name", None) or f"llm.{component_name}" + fallback_max_tokens = kwargs.pop("fallback_max_tokens", None) + if fallback_max_tokens is not None: + kwargs["max_tokens"] = self.profile_resolver.resolve_configured_value( + profile_name, + "max_tokens", + env_var="LLM_MAX_TOKENS", + fallback=fallback_max_tokens, + ) generation_name, generation_mapping_meta = _normalize_generation_name(self.telemetry, generation_name) effective = self.profile_resolver.resolve(profile_name, **kwargs) provider = str(effective.get("provider") or self.provider_name) diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc index 2b62fc7f..d985ade6 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/__pycache__/summary_memory.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/summary_memory.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/summary_memory.py index 024571b5..e1688fe3 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/summary_memory.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/memory/summary_memory.py @@ -167,7 +167,7 @@ class ConversationSummaryMemory: summary = await self.llm.ainvoke([ {"role": "system", "content": "Você resume memória conversacional para agentes corporativos."}, {"role": "user", "content": prompt}, - ], max_tokens=max(256, max_summary_chars // 4), temperature=0.1, profile_name="summary_memory", component_name="summary_memory", generation_name="llm.summary_memory") + ], fallback_max_tokens=max(256, max_summary_chars // 4), temperature=0.1, profile_name="summary_memory", component_name="summary_memory", generation_name="llm.summary_memory") summary = (summary or "").strip() if not summary: return self._deterministic_summary(previous_summary=previous_summary, messages=messages, max_chars=max_summary_chars) diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc index dfd1b6ac..0aa1f224 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/__pycache__/rag_service.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/rag_service.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/rag_service.py index b922606d..2fc8f7de 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/rag_service.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/rag/rag_service.py @@ -98,7 +98,7 @@ class RagService: {'role': 'user', 'content': prompt}, ], temperature=0, - max_tokens=300, + fallback_max_tokens=300, profile_name=profile_name, component_name=profile_name, generation_name=f"llm.{profile_name}", @@ -126,7 +126,7 @@ class RagService: {'role': 'user', 'content': prompt}, ], temperature=0, - max_tokens=max(512, max_chars // 3), + fallback_max_tokens=max(512, max_chars // 3), profile_name=profile_name, component_name=profile_name, generation_name=f"llm.{profile_name}", diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc index 7480b74c..cf41ee03 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/__pycache__/enterprise_router.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/enterprise_router.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/enterprise_router.py index f6ec8a73..bfb476a9 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/enterprise_router.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/routing/enterprise_router.py @@ -1045,7 +1045,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(payload, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=256, + fallback_max_tokens=256, profile_name="router", component_name="router.transaction_parameter_relevance", generation_name="llm.transaction_parameter_relevance", @@ -1328,7 +1328,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(user, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=512, + fallback_max_tokens=512, profile_name="router", component_name="router", generation_name="llm.transaction_intent_shift", @@ -1674,7 +1674,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(payload, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=768, + fallback_max_tokens=768, profile_name="router", component_name="router.multi_intent", generation_name="llm.router.multi_intent", @@ -1730,7 +1730,7 @@ class EnterpriseRouter: {"role": "user", "content": json.dumps(user, ensure_ascii=False)}, ], temperature=0.0, - max_tokens=512, + fallback_max_tokens=512, profile_name="router", component_name="router", generation_name="llm.router", diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc index c23d6d16..f14cadc3 100644 Binary files a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc and b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/__pycache__/agent_runtime.cpython-313.pyc differ diff --git a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py index 2ec6be62..c4ee75dc 100644 --- a/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py +++ b/agent_framework_oci/libs/agent_framework/src/agent_framework/runtime/agent_runtime.py @@ -849,7 +849,7 @@ class AgentRuntimeMixin: component_name="mcp_parameter_extraction", generation_name="llm.mcp_parameter_extraction", temperature=0.0, - max_tokens=80, + fallback_max_tokens=80, ) raw = self._llm_response_text(response).strip() payload = parse_json_object(raw) diff --git a/agent_framework_oci/templates/agent_template_backend/.env b/agent_framework_oci/templates/agent_template_backend/.env deleted file mode 100644 index 2a4774ef..00000000 --- a/agent_framework_oci/templates/agent_template_backend/.env +++ /dev/null @@ -1,250 +0,0 @@ -############################################################################### -# AI AGENT PLATFORM - CONFIGURAÇÃO ÚNICA -# Este arquivo é lido por Pydantic Settings no framework e no backend template. -############################################################################### - -APP_NAME=ai-agent-template -APP_ENV=local -LOG_LEVEL=INFO -API_HOST=0.0.0.0 -API_PORT=8000 -CORS_ORIGINS=http://localhost:5173,http://127.0.0.1:5173 - -############################################################################### -# LLM - OCI Generative AI como provider principal -############################################################################### -# Opções: mock, oci_openai, oci_sdk, openai_compatible -LLM_PROVIDER=oci_sdk -LLM_TEMPERATURE=0.2 -LLM_MAX_TOKENS=2048 -LLM_TIMEOUT_SECONDS=120 - -# OCI OpenAI-compatible endpoint -OCI_GENAI_BASE_URL=https://inference.generativeai.us-chicago-1.oci.oraclecloud.com -OCI_GENAI_MODEL=openai.gpt-4.1 -OCI_GENAI_API_KEY=sk-ph3FgX6iP3fxAQCXb9IpPIDTadkeeYAWntUWhzcWysIM6zsS -OCI_GENAI_PROJECT_OCID= - -#OCI_GENAI_BASE_URL=https://inference.generativeai.eu-frankfurt-1.oci.oraclecloud.com/openai/v1 -#OCI_GENAI_MODEL=ocid1.generativeaiendpoint.oc1.eu-frankfurt-1.amaaaaaad6nji3aa5fmicyft7qci6snu5idhwoomviehnsv4lrostzbmenkq -#OCI_GENAI_API_KEY=sk-TB0OzfrhPLXbQTqZ4aKlrLpcgjHAcn11O1o8C4I4aPvWF0Vx -#OCI_GENAI_PROJECT_OCID= - - -# OCI_AUTH_MODE=config_file|instance_principal|resource_principal -OCI_AUTH_MODE=config_file -# OCI SDK / signer / profiles -OCI_CONFIG_FILE=~/.oci/config -OCI_PROFILE=LATINOAMERICA-Chicago -OCI_COMPARTMENT_ID=ocid1.compartment.oc1..aaaaaaaaexpiw4a7dio64mkfv2t273s2hgdl6mgfvvyv7tycalnjlvpvfl3q -OCI_REGION=us-chicago-1 - -############################################################################### -# Persistência -############################################################################### -# Opções: memory, autonomous, mongodb -SESSION_REPOSITORY_PROVIDER=autonomous -MEMORY_REPOSITORY_PROVIDER=autonomous -CHECKPOINT_REPOSITORY_PROVIDER=autonomous - -# Autonomous Database -ADB_USER=admin -ADB_PASSWORD=Moniquinha19721972 -ADB_DSN=oradb23ai_high -ADB_WALLET_LOCATION=/mnt/d/Dropbox/ORACLE/LatinoAmerica/Wallet_ORADB23ai -ADB_WALLET_PASSWORD=Moniquinha1972 -ADB_TABLE_PREFIX=AGENTFW - -# MongoDB - também pode representar Autonomous usando API compatível com Mongo, se habilitada no ambiente -MONGODB_URI=mongodb://mongo:mongopassword@localhost:27017 -MONGODB_DATABASE=agent_platform - -# Redis -REDIS_URL=redis://localhost:6379/0 -ENABLE_REDIS_CACHE=false - -############################################################################### -# RAG / Vector / Graph -############################################################################### -VECTOR_STORE_PROVIDER=autonomous -GRAPH_STORE_PROVIDER=autonomous -RAG_TOP_K=5 -EMBEDDING_PROVIDER=oci -OCI_EMBEDDING_MODEL=cohere.embed-multilingual-v3.0 -RAG_FILE_GLOBS=*.md,*.txt,*.yaml,*.yml,*.json - -############################################################################### -# Observabilidade -############################################################################### -ENABLE_LANGFUSE=true - # Opcional: verbose, compact -LANGFUSE_TRACE_MODE=compact -# Nome customizado do trace pai, ex.: backoffice.checklist.workflow ou backoffice.emulador.workflow -LANGFUSE_COMPACT_VISIBLE_EVENT_PREFIXES=AGA.,NOC., IC. -LANGFUSE_COMPACT_SUPPRESSED_PREFIXES=llm.chat_completion -LANGFUSE_IGNORE_HEALTHCHECKS=true -LANGFUSE_IGNORED_PATHS=/health,/ready,/metrics -LANGFUSE_PUBLIC_KEY=pk-lf-4a1e3921-5158-4fd3-a16d-7a77549fb312 -LANGFUSE_SECRET_KEY=sk-lf-efc6fd59-c5ec-4858-b6ec-4aa129734915 -LANGFUSE_HOST=http://localhost:3005 -ENABLE_OTEL=false -OTEL_EXPORTER_OTLP_ENDPOINT= -OTEL_SERVICE_NAME=ai-agent-template -ENABLE_LANGFUSE_OPENAI_AUTO_INSTRUMENTATION=true -ENABLE_LANGFUSE_ANALYTICS_PUBLISHER=false - -############################################################################### -# Analytics / Observer corporativo -############################################################################### -# Quando true, AgentObserver publica eventos IC.*, NOC.* e GRL.* nos providers abaixo. -ENABLE_ANALYTICS=true -# Providers aceitos: oci_streaming,pubsub,noop -ANALYTICS_PROVIDERS=pubsub -# Compatibilidade FIRST/TIM: pode informar AGENT_PUBSUB_TOPIC diretamente. -AGENT_PUBSUB_TOPIC=teste_pubsub -PUBSUB_TOPIC_PATH=projects/project-7f829b68-bf43-442c-ad3/topics/teste_pubsub -PROJECT_ID=project-7f829b68-bf43-442c-ad3 -GCP_PUBSUB_TOPIC_PATH=projects/project-7f829b68-bf43-442c-ad3/topics/teste_pubsub -GCP_PROJECT_ID=project-7f829b68-bf43-442c-ad3 -GCP_PUBSUB_TOPIC=teste_pubsub -GCP_PUBSUB_TIMEOUT_SECONDS=30 -# Credencial GCP segue padrão Google: -GOOGLE_APPLICATION_CREDENTIALS=/mnt/d/Dropbox/ORACLE/TIM/FY27/Testes/sa-hoshikawa.json - -PUBSUB_SEQUENCE_ENABLED=true -PUBSUB_SEQUENCE_PROVIDER=mongodb - -#PUBSUB_SEQUENCE_MONGODB_URI=mongodb://mongo:mongopassword@localhost:27017 -#PUBSUB_SEQUENCE_MONGODB_DATABASE=agent_platform - -PUBSUB_SEQUENCE_MONGODB_URI=mongodb://ADMIN:Moniquinha1972@srlrz1eg.adb.sa-saopaulo-1.oraclecloudapps.com:37017/ADMIN?authMechanism=PLAIN&authSource=$external&ssl=true&retryWrites=false&loadBalanced=true -PUBSUB_SEQUENCE_MONGODB_DATABASE=ADMIN - -PUBSUB_SEQUENCE_MONGODB_COLLECTION=observer_event_counters - -PUBSUB_SEQUENCE_TTL_SECONDS=86400 -PUBSUB_SEQUENCE_KEY_PREFIX=observer:sequence - -PUBSUB_SEQUENCE_MEMORY_FALLBACK=false -SIMULATE_AGA_MISSING_TRANSACTION_ID=true -############################################################################### -# OCI Streaming -############################################################################### -ENABLE_OCI_STREAMING=false -OCI_STREAM_ENDPOINT= -OCI_STREAM_OCID= -OCI_STREAM_PARTITION_KEY=agent-events - -############################################################################### -# Guardrails, Judges, Supervisor -############################################################################### -ENABLE_INPUT_GUARDRAILS=true -ENABLE_OUTPUT_GUARDRAILS=true -ENABLE_JUDGES=true -ENABLE_SUPERVISOR=true -ENABLE_OUTPUT_SUPERVISOR=true -ENABLE_PARALLEL_GUARDRAILS=true -GUARDRAILS_FAIL_FAST=true -OUTPUT_SUPERVISOR_MAX_RETRIES=3 -GUARDRAILS_CONFIG_PATH=./config/guardrails.yaml -JUDGES_CONFIG_PATH=./config/judges.yaml -PROMPT_POLICY_PATH=./config/prompt_policy.yaml - -############################################################################### -# Gateway de canais -############################################################################### -DEFAULT_CHANNEL=web -# embedded = backend may parse simple/native channel payloads. -# external = backend only accepts GatewayRequest normalized by an external Channel Gateway. -FRAMEWORK_CHANNEL_INPUT_MODE=embedded -ENABLE_VOICE_ADAPTER=true -ENABLE_WHATSAPP_ADAPTER=true -ENABLE_TEXT_ADAPTER=true - -################################################# -# ENTERPRISE ROUTING -################################################# -# Arquivo YAML com intents, keywords, políticas de estado e fallback. -ROUTING_CONFIG_PATH=./config/routing.yaml -# true = usa LLM para classificar quando keywords/estado não resolverem. -# Em produção, costuma ser útil; em desenvolvimento, false evita custo e latência. -ENABLE_LLM_ROUTER=true - -# Semantic route stickiness (optional). -# Uses a lightweight LLM profile to decide only CONTINUE vs ROUTE. -# There are no regexes or deterministic language rules. -ENABLE_ROUTE_STICKINESS=true -ROUTE_STICKINESS_LLM_PROFILE=route_continuity -ROUTE_STICKINESS_CONFIDENCE_THRESHOLD=0.90 -ROUTE_STICKINESS_HISTORY_TURNS=2 -ROUTE_STICKINESS_MAX_TOKENS=80 -HUMAN_HANDOFF_MESSAGE=Vou encaminhar seu atendimento para uma pessoa. -END_SESSION_MESSAGE=Atendimento encerrado. Obrigado pelo contato. - -############################################################################### -# MCP / Tools -############################################################################### -ENABLE_MCP_TOOLS=true -MCP_SERVERS_CONFIG_PATH=./config/mcp_servers.yaml -TOOLS_CONFIG_PATH=./config/tools.yaml -MCP_TOOL_TIMEOUT_SECONDS=30 - -# router = EnterpriseRouter seleciona um agente; supervisor = pode acionar múltiplos agentes -ROUTING_MODE=router - -# Usage/cost accounting -USAGE_REPOSITORY_PROVIDER=autonomous -IDENTITY_CONFIG_PATH=./config/identity.yaml -MCP_PARAMETER_MAPPING_PATH=./config/mcp_parameter_mapping.yaml - -# ----------------------------------------------------------------------------- -# ConversationSummaryMemory / compressão de contexto conversacional -# ----------------------------------------------------------------------------- -ENABLE_CONVERSATION_SUMMARY_MEMORY=true -MEMORY_CONTEXT_STRATEGY=summary -MEMORY_HISTORY_LIMIT=80 -MEMORY_RECENT_MESSAGES_LIMIT=8 -MEMORY_SUMMARY_TRIGGER_MESSAGES=20 -MEMORY_MAX_SUMMARY_CHARS=6000 -MEMORY_SUMMARY_USE_LLM=true -MEMORY_INJECT_RECENT_MESSAGES=true -MEMORY_INJECT_SUMMARY=true - -############################################################################### -# LONG-TERM MEMORY -############################################################################### -ENABLE_LONG_TERM_MEMORY=true -LONG_TERM_MEMORY_PROVIDER=sqlite -LONG_TERM_MEMORY_SQLITE_PATH=./data/agent_framework.db -LONG_TERM_MEMORY_TABLE=agentfw_long_term_memory -# For Autonomous/Oracle, defaults to ${ADB_TABLE_PREFIX}_LONG_TERM_MEMORY -# LONG_TERM_MEMORY_ORACLE_TABLE=AGENTFW_LONG_TERM_MEMORY -LONG_TERM_MEMORY_MAX_CONTEXT_ITEMS=20 -LONG_TERM_MEMORY_MIN_CONFIDENCE=0.70 -LONG_TERM_MEMORY_AUTO_EXTRACT=true -LONG_TERM_MEMORY_INJECT_CONTEXT=true - -############################################################################### -# RAG provider selection (mutually exclusive at runtime) -############################################################################### -# standard = RAG original do agent_framework_oci (default, backward compatible) -# kbdb = KBDB enterprise via PKG_KB_SERVING.SEARCH_KNOWLEDGE_BASE -RAG_PROVIDER=kbdb - -# Somente usados quando RAG_PROVIDER=kbdb. Se vazios, credenciais caem para ADB_*. -KBDB_DB_USER=KB_USER -KBDB_DB_PASSWORD=SuperStr0ngPa##w0rd -KBDB_DB_DSN=kbdb_public_high -KBDB_DB_WALLET_LOCATION=/mnt/d/Dropbox/ORACLE/TIM/FY27/kb/Wallet_kbdb -KBDB_DB_WALLET_PASSWORD=SuperStr0ngPa##w0rd -KBDB_SEARCH_TYPE=hybrid -KBDB_NODE_EXPANSION=true -KBDB_NODE_MAX_RELATED=8 -KBDB_GRAPH_CROSS_REF=false -KBDB_MAX_CROSS_REF_HOPS=1 -KBDB_DOCUMENT_TYPE=customer_safe -KBDB_METADATA_JSON= -KBDB_MIN_SCORE=0.5 -KBDB_IDENTIFY_DOCUMENT=true -KBDB_STORE_QUERY=true -KBDB_IDENTIFY_TOP_N=3 \ No newline at end of file diff --git a/agent_framework_oci/templates/agent_template_backend/data/agent_framework.db b/agent_framework_oci/templates/agent_template_backend/data/agent_framework.db deleted file mode 100644 index f767effa..00000000 Binary files a/agent_framework_oci/templates/agent_template_backend/data/agent_framework.db and /dev/null differ diff --git a/agent_framework_oci/templates/agent_template_backend/llm_profiles.yaml b/agent_framework_oci/templates/agent_template_backend/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/templates/agent_template_backend/llm_profiles.yaml +++ b/agent_framework_oci/templates/agent_template_backend/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/templates/agent_template_backend_day_zero/llm_profiles.yaml b/agent_framework_oci/templates/agent_template_backend_day_zero/llm_profiles.yaml index 29fda415..93e04010 100644 --- a/agent_framework_oci/templates/agent_template_backend_day_zero/llm_profiles.yaml +++ b/agent_framework_oci/templates/agent_template_backend_day_zero/llm_profiles.yaml @@ -15,11 +15,17 @@ profiles: temperature: 0 max_tokens: 80 timeout_seconds: 5 + processing_interruption_classifier: + provider: oci_openai + model: openai.gpt-4.1-mini + temperature: 0 + max_tokens: 8 + timeout_seconds: 5 router: provider: oci_openai model: openai.gpt-4.1 temperature: 0 - max_tokens: 500 + max_tokens: 768 guardrail: provider: oci_openai model: openai.gpt-4.1 diff --git a/agent_framework_oci/tests/__pycache__/test_llm_max_tokens_configuration.cpython-313-pytest-9.0.2.pyc b/agent_framework_oci/tests/__pycache__/test_llm_max_tokens_configuration.cpython-313-pytest-9.0.2.pyc new file mode 100644 index 00000000..d22753a1 Binary files /dev/null and b/agent_framework_oci/tests/__pycache__/test_llm_max_tokens_configuration.cpython-313-pytest-9.0.2.pyc differ diff --git a/agent_framework_oci/tests/test_llm_max_tokens_configuration.py b/agent_framework_oci/tests/test_llm_max_tokens_configuration.py new file mode 100644 index 00000000..c2580881 --- /dev/null +++ b/agent_framework_oci/tests/test_llm_max_tokens_configuration.py @@ -0,0 +1,95 @@ +from __future__ import annotations + +import os +import sys +from pathlib import Path +from types import SimpleNamespace + +import yaml + +ROOT = Path(__file__).resolve().parents[1] +LIB = ROOT / "libs" / "agent_framework" / "src" +if str(LIB) not in sys.path: + sys.path.insert(0, str(LIB)) + +from agent_framework.llm.profile_resolver import LLMProfileResolver + + +def _settings(path: Path): + return SimpleNamespace( + LLM_PROFILES_PATH=str(path), + LLM_PROVIDER="oci_openai", + OCI_GENAI_MODEL="openai.gpt-4.1", + LLM_TEMPERATURE=0.2, + LLM_MAX_TOKENS=2048, + LLM_TIMEOUT_SECONDS=120, + OCI_GENAI_BASE_URL="", + OCI_GENAI_API_KEY=None, + OCI_GENAI_PROJECT_OCID=None, + OCI_AUTH_MODE="config_file", + OCI_GENAI_ENDPOINT=None, + OCI_REGION="", + model_fields_set=set(), + ) + + +def test_profile_max_tokens_wins_over_env_and_legacy_fallback(tmp_path, monkeypatch): + profile = tmp_path / "llm_profiles.yaml" + profile.write_text( + "profiles:\n" + " default:\n" + " provider: oci_openai\n" + " router:\n" + " max_tokens: 768\n", + encoding="utf-8", + ) + monkeypatch.setenv("LLM_MAX_TOKENS", "999") + resolver = LLMProfileResolver.from_settings(_settings(profile)) + assert resolver.resolve_configured_value( + "router", "max_tokens", env_var="LLM_MAX_TOKENS", fallback=512 + ) == 768 + + +def test_env_max_tokens_wins_when_profiles_file_is_absent(tmp_path, monkeypatch): + missing = tmp_path / "missing.yaml" + monkeypatch.setenv("LLM_MAX_TOKENS", "901") + resolver = LLMProfileResolver.from_settings(_settings(missing)) + assert resolver.resolve_configured_value( + "router", "max_tokens", env_var="LLM_MAX_TOKENS", fallback=512 + ) == 901 + + +def test_legacy_fallback_is_kept_when_yaml_and_env_are_absent(tmp_path, monkeypatch): + missing = tmp_path / "missing.yaml" + monkeypatch.delenv("LLM_MAX_TOKENS", raising=False) + resolver = LLMProfileResolver.from_settings(_settings(missing)) + assert resolver.resolve_configured_value( + "router", "max_tokens", env_var="LLM_MAX_TOKENS", fallback=512 + ) == 512 + + +def test_canonical_profiles_keep_existing_budgets_and_router_uses_largest_value(): + profile_path = ROOT / "libs" / "agent_framework" / "config" / "llm_profiles.yaml" + profiles = yaml.safe_load(profile_path.read_text(encoding="utf-8"))["profiles"] + assert profiles["router"]["max_tokens"] == 768 + assert profiles["processing_interruption_classifier"]["max_tokens"] == 8 + assert profiles["mcp_parameter_extraction"]["max_tokens"] == 80 + assert profiles["guardrail"]["max_tokens"] == 600 + assert profiles["rag_rewriter"]["max_tokens"] == 300 + assert profiles["rag_compressor"]["max_tokens"] == 1200 + assert profiles["summary_memory"]["max_tokens"] == 1200 + + +def test_inference_points_use_fallback_max_tokens_instead_of_direct_max_tokens(): + checks = { + "libs/agent_framework/src/agent_framework/routing/enterprise_router.py": [256, 512, 768], + "libs/agent_framework/src/agent_framework/runtime/agent_runtime.py": [80], + "libs/agent_framework/src/agent_framework/channels/interruption.py": [8], + "libs/agent_framework/src/agent_framework/guardrails/llm_rails.py": [600], + "libs/agent_framework/src/agent_framework/rag/rag_service.py": [300], + } + for relative, values in checks.items(): + text = (ROOT / relative).read_text(encoding="utf-8") + for value in values: + assert f"fallback_max_tokens={value}" in text + assert f"max_tokens={value}," not in text.replace(f"fallback_max_tokens={value},", "")