mirror of
https://github.com/hoshikawa2/agent_platform_oci.git
synced 2026-11-05 19:04:13 +00:00
bugfix: max_tokens hardcoded
This commit is contained in:
@@ -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}",
|
||||
|
||||
@@ -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}",
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Binary file not shown.
@@ -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}",
|
||||
|
||||
Binary file not shown.
@@ -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}",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Binary file not shown.
@@ -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)
|
||||
|
||||
Binary file not shown.
@@ -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}",
|
||||
|
||||
Binary file not shown.
@@ -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",
|
||||
|
||||
Binary file not shown.
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user