Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2128e28ded | ||
|
|
3af232f7c0 | ||
|
|
9be7bb0d57 | ||
|
|
6524bbbc71 |
@@ -1058,6 +1058,19 @@ class CreateBankRequest(BaseModel):
|
||||
default=None,
|
||||
description="Controls what gets synthesised into observations. Replaces built-in consolidation rules entirely.",
|
||||
)
|
||||
# RAG mode retrieval settings
|
||||
enable_temporal_extraction: bool | None = Field(
|
||||
default=None,
|
||||
description="Toggle temporal extraction during recall. Disable for lower latency.",
|
||||
)
|
||||
enable_graph_retrieval: bool | None = Field(
|
||||
default=None,
|
||||
description="Toggle entity/link graph traversal during recall. Disable for lower latency.",
|
||||
)
|
||||
enable_reranking: bool | None = Field(
|
||||
default=None,
|
||||
description="Toggle cross-encoder reranking during recall. Disable for lower latency.",
|
||||
)
|
||||
|
||||
def get_config_updates(self) -> dict[str, Any]:
|
||||
"""Return only the config fields that were explicitly set.
|
||||
@@ -1090,6 +1103,9 @@ class CreateBankRequest(BaseModel):
|
||||
"retain_chunk_size",
|
||||
"enable_observations",
|
||||
"observations_mission",
|
||||
"enable_temporal_extraction",
|
||||
"enable_graph_retrieval",
|
||||
"enable_reranking",
|
||||
):
|
||||
value = getattr(self, field_name)
|
||||
if value is not None:
|
||||
@@ -1662,6 +1678,15 @@ class BankTemplateConfig(BaseModel):
|
||||
default=None, description="Custom extraction prompt (when mode='custom')"
|
||||
)
|
||||
retain_chunk_size: int | None = Field(default=None, description="Max token size for each content chunk")
|
||||
enable_temporal_extraction: bool | None = Field(
|
||||
default=None, description="Toggle dateparser temporal extraction during recall"
|
||||
)
|
||||
enable_graph_retrieval: bool | None = Field(
|
||||
default=None, description="Toggle entity/link graph traversal during recall"
|
||||
)
|
||||
enable_reranking: bool | None = Field(
|
||||
default=None, description="Toggle cross-encoder reranking during recall"
|
||||
)
|
||||
enable_observations: bool | None = Field(default=None, description="Toggle observation consolidation")
|
||||
observations_mission: str | None = Field(default=None, description="Controls what gets synthesised")
|
||||
disposition_skepticism: int | None = Field(default=None, ge=1, le=5, description="Skepticism trait (1-5)")
|
||||
@@ -1673,6 +1698,61 @@ class BankTemplateConfig(BaseModel):
|
||||
entities_allow_free_form: bool | None = Field(
|
||||
default=None, description="Allow entities outside the label vocabulary"
|
||||
)
|
||||
retain_default_strategy: str | None = Field(
|
||||
default=None, description="Name of the default retain strategy (key into retain_strategies map)"
|
||||
)
|
||||
retain_strategies: dict | None = Field(
|
||||
default=None, description="Map of retain strategy name to per-strategy config dict"
|
||||
)
|
||||
retain_chunk_batch_size: int | None = Field(
|
||||
default=None, description="Max chunks per streaming batch (0 disables batching)"
|
||||
)
|
||||
mcp_enabled_tools: list[str] | None = Field(
|
||||
default=None, description="MCP tool allowlist for this bank (None = all tools)"
|
||||
)
|
||||
consolidation_llm_batch_size: int | None = Field(
|
||||
default=None, description="LLM batch size for observation consolidation"
|
||||
)
|
||||
consolidation_source_facts_max_tokens: int | None = Field(
|
||||
default=None, description="Max tokens of source facts per consolidation batch"
|
||||
)
|
||||
consolidation_source_facts_max_tokens_per_observation: int | None = Field(
|
||||
default=None, description="Max tokens of source facts per observation"
|
||||
)
|
||||
max_observations_per_scope: int | None = Field(
|
||||
default=None, description="Max observations to retain per consolidation scope"
|
||||
)
|
||||
reflect_source_facts_max_tokens: int | None = Field(
|
||||
default=None, description="Max tokens of source facts per reflect call"
|
||||
)
|
||||
llm_gemini_safety_settings: list | None = Field(
|
||||
default=None, description="Per-bank Gemini/VertexAI safety filter settings"
|
||||
)
|
||||
recall_budget_function: str | None = Field(
|
||||
default=None, description="Recall budget mapping function: 'fixed' or 'adaptive'"
|
||||
)
|
||||
recall_budget_fixed_low: int | None = Field(
|
||||
default=None, description="Fixed thinking_budget for budget=low (function='fixed')"
|
||||
)
|
||||
recall_budget_fixed_mid: int | None = Field(
|
||||
default=None, description="Fixed thinking_budget for budget=mid (function='fixed')"
|
||||
)
|
||||
recall_budget_fixed_high: int | None = Field(
|
||||
default=None, description="Fixed thinking_budget for budget=high (function='fixed')"
|
||||
)
|
||||
recall_budget_adaptive_low: float | None = Field(
|
||||
default=None, description="Ratio of max_tokens for budget=low (function='adaptive')"
|
||||
)
|
||||
recall_budget_adaptive_mid: float | None = Field(
|
||||
default=None, description="Ratio of max_tokens for budget=mid (function='adaptive')"
|
||||
)
|
||||
recall_budget_adaptive_high: float | None = Field(
|
||||
default=None, description="Ratio of max_tokens for budget=high (function='adaptive')"
|
||||
)
|
||||
recall_budget_min: int | None = Field(default=None, description="Floor for the adaptive function (after clamping)")
|
||||
recall_budget_max: int | None = Field(
|
||||
default=None, description="Ceiling for the adaptive function (after clamping)"
|
||||
)
|
||||
|
||||
def get_config_updates(self) -> dict[str, Any]:
|
||||
"""Return only the fields that were explicitly set (non-None)."""
|
||||
|
||||
@@ -325,6 +325,21 @@ ENV_FILE_CONVERSION_MAX_BATCH_SIZE = "HINDSIGHT_API_FILE_CONVERSION_MAX_BATCH_SI
|
||||
ENV_ENABLE_FILE_UPLOAD_API = "HINDSIGHT_API_ENABLE_FILE_UPLOAD_API"
|
||||
ENV_FILE_DELETE_AFTER_RETAIN = "HINDSIGHT_API_FILE_DELETE_AFTER_RETAIN"
|
||||
|
||||
# Temporal extraction — dateparser-based query analysis for date-aware recall.
|
||||
# Adds ~120ms per recall. Disable to reduce recall latency when temporal
|
||||
# filtering is not needed.
|
||||
ENV_ENABLE_TEMPORAL_EXTRACTION = "HINDSIGHT_API_ENABLE_TEMPORAL_EXTRACTION"
|
||||
|
||||
# Graph retrieval — entity/link-based graph traversal during recall.
|
||||
# Disable to reduce recall latency when only semantic + BM25 retrieval is needed
|
||||
# (e.g. pure RAG / chunks mode).
|
||||
ENV_ENABLE_GRAPH_RETRIEVAL = "HINDSIGHT_API_ENABLE_GRAPH_RETRIEVAL"
|
||||
|
||||
# Reranking — cross-encoder reranking of candidates during recall.
|
||||
# Disable to skip the cross-encoder scoring step and use RRF-merged scores
|
||||
# directly. Significantly reduces recall latency on large banks.
|
||||
ENV_ENABLE_RERANKING = "HINDSIGHT_API_ENABLE_RERANKING"
|
||||
|
||||
# Observations settings (consolidated knowledge from facts)
|
||||
ENV_ENABLE_OBSERVATIONS = "HINDSIGHT_API_ENABLE_OBSERVATIONS"
|
||||
ENV_CONSOLIDATION_BATCH_SIZE = "HINDSIGHT_API_CONSOLIDATION_BATCH_SIZE"
|
||||
@@ -383,6 +398,17 @@ ENV_REFLECT_WALL_TIMEOUT = "HINDSIGHT_API_REFLECT_WALL_TIMEOUT"
|
||||
ENV_REFLECT_MISSION = "HINDSIGHT_API_REFLECT_MISSION"
|
||||
ENV_REFLECT_SOURCE_FACTS_MAX_TOKENS = "HINDSIGHT_API_REFLECT_SOURCE_FACTS_MAX_TOKENS"
|
||||
|
||||
# Recall budget mapping (budget enum -> thinking_budget integer)
|
||||
ENV_RECALL_BUDGET_FUNCTION = "HINDSIGHT_API_RECALL_BUDGET_FUNCTION"
|
||||
ENV_RECALL_BUDGET_FIXED_LOW = "HINDSIGHT_API_RECALL_BUDGET_FIXED_LOW"
|
||||
ENV_RECALL_BUDGET_FIXED_MID = "HINDSIGHT_API_RECALL_BUDGET_FIXED_MID"
|
||||
ENV_RECALL_BUDGET_FIXED_HIGH = "HINDSIGHT_API_RECALL_BUDGET_FIXED_HIGH"
|
||||
ENV_RECALL_BUDGET_ADAPTIVE_LOW = "HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_LOW"
|
||||
ENV_RECALL_BUDGET_ADAPTIVE_MID = "HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_MID"
|
||||
ENV_RECALL_BUDGET_ADAPTIVE_HIGH = "HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_HIGH"
|
||||
ENV_RECALL_BUDGET_MIN = "HINDSIGHT_API_RECALL_BUDGET_MIN"
|
||||
ENV_RECALL_BUDGET_MAX = "HINDSIGHT_API_RECALL_BUDGET_MAX"
|
||||
|
||||
# Audit log settings
|
||||
ENV_AUDIT_LOG_ENABLED = "HINDSIGHT_API_AUDIT_LOG_ENABLED"
|
||||
ENV_AUDIT_LOG_ACTIONS = "HINDSIGHT_API_AUDIT_LOG_ACTIONS"
|
||||
@@ -540,6 +566,10 @@ DEFAULT_ENABLE_FILE_UPLOAD_API = True # Enable file upload endpoint
|
||||
DEFAULT_FILE_DELETE_AFTER_RETAIN = True # Delete file bytes after retain (saves storage)
|
||||
|
||||
# Observations defaults (consolidated knowledge from facts)
|
||||
DEFAULT_ENABLE_TEMPORAL_EXTRACTION = True # Temporal extraction enabled by default
|
||||
DEFAULT_ENABLE_GRAPH_RETRIEVAL = True # Graph retrieval enabled by default
|
||||
DEFAULT_ENABLE_RERANKING = True # Cross-encoder reranking enabled by default
|
||||
|
||||
DEFAULT_ENABLE_OBSERVATIONS = True # Observations enabled by default
|
||||
DEFAULT_ENABLE_OBSERVATION_HISTORY = True # Observation history tracking enabled by default
|
||||
DEFAULT_ENABLE_MENTAL_MODEL_HISTORY = True # Mental model history tracking enabled by default
|
||||
@@ -580,6 +610,22 @@ DEFAULT_REFLECT_MAX_CONTEXT_TOKENS = 100_000 # Max accumulated context tokens b
|
||||
DEFAULT_REFLECT_WALL_TIMEOUT = 300 # Wall-clock timeout in seconds for the entire reflect operation (5 minutes)
|
||||
DEFAULT_REFLECT_SOURCE_FACTS_MAX_TOKENS = -1 # Token budget for source facts in search_observations (-1 = disabled)
|
||||
|
||||
# Recall budget mapping
|
||||
# "fixed": thinking_budget = recall_budget_fixed_<level> (preserves legacy behavior)
|
||||
# "adaptive": thinking_budget = round(max_tokens * recall_budget_adaptive_<level>),
|
||||
# clamped to [recall_budget_min, recall_budget_max]
|
||||
RECALL_BUDGET_FUNCTIONS = ("fixed", "adaptive")
|
||||
DEFAULT_RECALL_BUDGET_FUNCTION = "fixed"
|
||||
DEFAULT_RECALL_BUDGET_FIXED_LOW = 100
|
||||
DEFAULT_RECALL_BUDGET_FIXED_MID = 300
|
||||
DEFAULT_RECALL_BUDGET_FIXED_HIGH = 1000
|
||||
# Adaptive defaults chosen to roughly match fixed defaults at max_tokens=4096
|
||||
DEFAULT_RECALL_BUDGET_ADAPTIVE_LOW = 0.025
|
||||
DEFAULT_RECALL_BUDGET_ADAPTIVE_MID = 0.075
|
||||
DEFAULT_RECALL_BUDGET_ADAPTIVE_HIGH = 0.25
|
||||
DEFAULT_RECALL_BUDGET_MIN = 20 # Floor for the adaptive function
|
||||
DEFAULT_RECALL_BUDGET_MAX = 2000 # Ceiling for the adaptive function
|
||||
|
||||
# Disposition defaults (None = not set, fall back to bank DB value or 3)
|
||||
DEFAULT_DISPOSITION_SKEPTICISM = None
|
||||
DEFAULT_DISPOSITION_LITERALISM = None
|
||||
@@ -673,6 +719,18 @@ def _validate_extraction_mode(mode: str) -> str:
|
||||
return mode_lower
|
||||
|
||||
|
||||
def _validate_recall_budget_function(function: str) -> str:
|
||||
"""Validate and normalize recall budget function."""
|
||||
function_lower = function.lower()
|
||||
if function_lower not in RECALL_BUDGET_FUNCTIONS:
|
||||
logger.warning(
|
||||
f"Invalid recall budget function '{function}', must be one of {RECALL_BUDGET_FUNCTIONS}. "
|
||||
f"Defaulting to '{DEFAULT_RECALL_BUDGET_FUNCTION}'."
|
||||
)
|
||||
return DEFAULT_RECALL_BUDGET_FUNCTION
|
||||
return function_lower
|
||||
|
||||
|
||||
def _get_default_model_for_provider(provider: str) -> str:
|
||||
"""Get the default model for a given provider."""
|
||||
return PROVIDER_DEFAULT_MODELS.get(provider.lower(), DEFAULT_LLM_MODEL)
|
||||
@@ -892,6 +950,9 @@ class HindsightConfig:
|
||||
file_delete_after_retain: bool
|
||||
|
||||
# Observations settings (consolidated knowledge from facts)
|
||||
enable_temporal_extraction: bool
|
||||
enable_graph_retrieval: bool
|
||||
enable_reranking: bool
|
||||
enable_observations: bool
|
||||
enable_observation_history: bool
|
||||
enable_mental_model_history: bool
|
||||
@@ -914,6 +975,25 @@ class HindsightConfig:
|
||||
reflect_mission: str | None
|
||||
reflect_source_facts_max_tokens: int
|
||||
|
||||
# Recall settings (used by internal recall, e.g. during mental model refresh)
|
||||
recall_include_chunks: bool
|
||||
recall_max_tokens: int
|
||||
recall_chunks_max_tokens: int
|
||||
|
||||
# Recall budget mapping: how the Budget enum (LOW/MID/HIGH) maps to thinking_budget integer.
|
||||
# function="fixed": use the recall_budget_fixed_* values directly (legacy behavior).
|
||||
# function="adaptive": compute round(max_tokens * recall_budget_adaptive_*),
|
||||
# clamped to [recall_budget_min, recall_budget_max].
|
||||
recall_budget_function: str
|
||||
recall_budget_fixed_low: int
|
||||
recall_budget_fixed_mid: int
|
||||
recall_budget_fixed_high: int
|
||||
recall_budget_adaptive_low: float
|
||||
recall_budget_adaptive_mid: float
|
||||
recall_budget_adaptive_high: float
|
||||
recall_budget_min: int
|
||||
recall_budget_max: int
|
||||
|
||||
# Disposition settings (hierarchical - can be overridden per bank; None = fall back to DB)
|
||||
disposition_skepticism: int | None
|
||||
disposition_literalism: int | None
|
||||
@@ -1016,6 +1096,10 @@ class HindsightConfig:
|
||||
# Entity labels (controlled vocabulary for entity classification)
|
||||
"entity_labels",
|
||||
"entities_allow_free_form",
|
||||
# RAG mode — per-bank retrieval pipeline control
|
||||
"enable_temporal_extraction",
|
||||
"enable_graph_retrieval",
|
||||
"enable_reranking",
|
||||
# Consolidation settings
|
||||
"enable_observations",
|
||||
"consolidation_llm_batch_size",
|
||||
@@ -1026,6 +1110,20 @@ class HindsightConfig:
|
||||
# Reflect settings
|
||||
"reflect_mission",
|
||||
"reflect_source_facts_max_tokens",
|
||||
# Recall settings (used by internal recall, e.g. mental model refresh)
|
||||
"recall_include_chunks",
|
||||
"recall_max_tokens",
|
||||
"recall_chunks_max_tokens",
|
||||
# Recall budget mapping (Budget enum -> thinking_budget integer)
|
||||
"recall_budget_function",
|
||||
"recall_budget_fixed_low",
|
||||
"recall_budget_fixed_mid",
|
||||
"recall_budget_fixed_high",
|
||||
"recall_budget_adaptive_low",
|
||||
"recall_budget_adaptive_mid",
|
||||
"recall_budget_adaptive_high",
|
||||
"recall_budget_min",
|
||||
"recall_budget_max",
|
||||
# Disposition settings
|
||||
"disposition_skepticism",
|
||||
"disposition_literalism",
|
||||
@@ -1443,6 +1541,17 @@ class HindsightConfig:
|
||||
ENV_FILE_DELETE_AFTER_RETAIN, str(DEFAULT_FILE_DELETE_AFTER_RETAIN)
|
||||
).lower()
|
||||
== "true",
|
||||
# Temporal extraction (dateparser query analysis for date-aware recall)
|
||||
enable_temporal_extraction=os.getenv(
|
||||
ENV_ENABLE_TEMPORAL_EXTRACTION, str(DEFAULT_ENABLE_TEMPORAL_EXTRACTION)
|
||||
).lower()
|
||||
== "true",
|
||||
# Graph retrieval (entity/link traversal during recall)
|
||||
enable_graph_retrieval=os.getenv(ENV_ENABLE_GRAPH_RETRIEVAL, str(DEFAULT_ENABLE_GRAPH_RETRIEVAL)).lower()
|
||||
== "true",
|
||||
# Reranking (cross-encoder scoring during recall)
|
||||
enable_reranking=os.getenv(ENV_ENABLE_RERANKING, str(DEFAULT_ENABLE_RERANKING)).lower()
|
||||
== "true",
|
||||
# Observations settings (consolidated knowledge from facts)
|
||||
enable_observations=os.getenv(ENV_ENABLE_OBSERVATIONS, str(DEFAULT_ENABLE_OBSERVATIONS)).lower() == "true",
|
||||
enable_observation_history=os.getenv(
|
||||
@@ -1505,6 +1614,31 @@ class HindsightConfig:
|
||||
reflect_source_facts_max_tokens=int(
|
||||
os.getenv(ENV_REFLECT_SOURCE_FACTS_MAX_TOKENS, str(DEFAULT_REFLECT_SOURCE_FACTS_MAX_TOKENS))
|
||||
),
|
||||
recall_include_chunks=os.getenv(ENV_RECALL_INCLUDE_CHUNKS, str(DEFAULT_RECALL_INCLUDE_CHUNKS)).lower()
|
||||
in ("true", "1", "yes"),
|
||||
recall_max_tokens=int(os.getenv(ENV_RECALL_MAX_TOKENS, str(DEFAULT_RECALL_MAX_TOKENS))),
|
||||
recall_chunks_max_tokens=int(
|
||||
os.getenv(ENV_RECALL_CHUNKS_MAX_TOKENS, str(DEFAULT_RECALL_CHUNKS_MAX_TOKENS))
|
||||
),
|
||||
recall_budget_function=_validate_recall_budget_function(
|
||||
os.getenv(ENV_RECALL_BUDGET_FUNCTION, DEFAULT_RECALL_BUDGET_FUNCTION)
|
||||
),
|
||||
recall_budget_fixed_low=int(os.getenv(ENV_RECALL_BUDGET_FIXED_LOW, str(DEFAULT_RECALL_BUDGET_FIXED_LOW))),
|
||||
recall_budget_fixed_mid=int(os.getenv(ENV_RECALL_BUDGET_FIXED_MID, str(DEFAULT_RECALL_BUDGET_FIXED_MID))),
|
||||
recall_budget_fixed_high=int(
|
||||
os.getenv(ENV_RECALL_BUDGET_FIXED_HIGH, str(DEFAULT_RECALL_BUDGET_FIXED_HIGH))
|
||||
),
|
||||
recall_budget_adaptive_low=float(
|
||||
os.getenv(ENV_RECALL_BUDGET_ADAPTIVE_LOW, str(DEFAULT_RECALL_BUDGET_ADAPTIVE_LOW))
|
||||
),
|
||||
recall_budget_adaptive_mid=float(
|
||||
os.getenv(ENV_RECALL_BUDGET_ADAPTIVE_MID, str(DEFAULT_RECALL_BUDGET_ADAPTIVE_MID))
|
||||
),
|
||||
recall_budget_adaptive_high=float(
|
||||
os.getenv(ENV_RECALL_BUDGET_ADAPTIVE_HIGH, str(DEFAULT_RECALL_BUDGET_ADAPTIVE_HIGH))
|
||||
),
|
||||
recall_budget_min=int(os.getenv(ENV_RECALL_BUDGET_MIN, str(DEFAULT_RECALL_BUDGET_MIN))),
|
||||
recall_budget_max=int(os.getenv(ENV_RECALL_BUDGET_MAX, str(DEFAULT_RECALL_BUDGET_MAX))),
|
||||
# Disposition settings (None = fall back to DB value)
|
||||
disposition_skepticism=int(os.getenv(ENV_DISPOSITION_SKEPTICISM))
|
||||
if os.getenv(ENV_DISPOSITION_SKEPTICISM)
|
||||
|
||||
@@ -15,7 +15,12 @@ from typing import Any
|
||||
|
||||
import asyncpg
|
||||
|
||||
from hindsight_api.config import HindsightConfig, _get_raw_config, normalize_config_dict
|
||||
from hindsight_api.config import (
|
||||
RECALL_BUDGET_FUNCTIONS,
|
||||
HindsightConfig,
|
||||
_get_raw_config,
|
||||
normalize_config_dict,
|
||||
)
|
||||
from hindsight_api.engine.memory_engine import fq_table
|
||||
from hindsight_api.extensions.tenant import TenantExtension
|
||||
from hindsight_api.models import RequestContext
|
||||
@@ -256,6 +261,9 @@ class ConfigResolver:
|
||||
"Strategy names must not be empty strings. Remove entries with empty names before saving."
|
||||
)
|
||||
|
||||
# Validate recall budget fields
|
||||
_validate_recall_budget_updates(normalized_updates)
|
||||
|
||||
# Merge with existing config (JSONB || operator)
|
||||
async with self.pool.acquire() as conn:
|
||||
await conn.execute(
|
||||
@@ -292,6 +300,53 @@ class ConfigResolver:
|
||||
logger.info(f"Reset bank config for {bank_id} to defaults")
|
||||
|
||||
|
||||
_RECALL_BUDGET_FIXED_KEYS = (
|
||||
"recall_budget_fixed_low",
|
||||
"recall_budget_fixed_mid",
|
||||
"recall_budget_fixed_high",
|
||||
)
|
||||
_RECALL_BUDGET_ADAPTIVE_KEYS = (
|
||||
"recall_budget_adaptive_low",
|
||||
"recall_budget_adaptive_mid",
|
||||
"recall_budget_adaptive_high",
|
||||
)
|
||||
|
||||
|
||||
def _validate_recall_budget_updates(updates: dict[str, Any]) -> None:
|
||||
"""Validate recall budget config updates. Raises ValueError on invalid input."""
|
||||
if "recall_budget_function" in updates:
|
||||
function = updates["recall_budget_function"]
|
||||
if not isinstance(function, str) or function.lower() not in RECALL_BUDGET_FUNCTIONS:
|
||||
raise ValueError(
|
||||
f"recall_budget_function must be one of {sorted(RECALL_BUDGET_FUNCTIONS)}, got {function!r}"
|
||||
)
|
||||
|
||||
for key in _RECALL_BUDGET_FIXED_KEYS:
|
||||
if key in updates:
|
||||
value = updates[key]
|
||||
if not isinstance(value, int) or isinstance(value, bool) or value < 1:
|
||||
raise ValueError(f"{key} must be a positive integer, got {value!r}")
|
||||
|
||||
for key in _RECALL_BUDGET_ADAPTIVE_KEYS:
|
||||
if key in updates:
|
||||
value = updates[key]
|
||||
if isinstance(value, bool) or not isinstance(value, (int, float)) or value <= 0:
|
||||
raise ValueError(f"{key} must be a positive number, got {value!r}")
|
||||
|
||||
for key in ("recall_budget_min", "recall_budget_max"):
|
||||
if key in updates:
|
||||
value = updates[key]
|
||||
if not isinstance(value, int) or isinstance(value, bool) or value < 1:
|
||||
raise ValueError(f"{key} must be a positive integer, got {value!r}")
|
||||
|
||||
if "recall_budget_min" in updates and "recall_budget_max" in updates:
|
||||
if updates["recall_budget_min"] > updates["recall_budget_max"]:
|
||||
raise ValueError(
|
||||
f"recall_budget_min ({updates['recall_budget_min']}) must be <= "
|
||||
f"recall_budget_max ({updates['recall_budget_max']})"
|
||||
)
|
||||
|
||||
|
||||
def apply_strategy(config: HindsightConfig, strategy_name: str) -> HindsightConfig:
|
||||
"""
|
||||
Apply a named retain strategy's overrides on top of a resolved config.
|
||||
|
||||
@@ -205,6 +205,39 @@ class Budget(str, Enum):
|
||||
HIGH = "high"
|
||||
|
||||
|
||||
def _resolve_thinking_budget(config_dict: dict, budget: "Budget | None", max_tokens: int) -> int:
|
||||
"""
|
||||
Map a Budget enum level to the integer thinking_budget passed to retrieval.
|
||||
|
||||
Reads the bank-resolved config to decide between two functions:
|
||||
- "fixed": returns recall_budget_fixed_<level> directly (legacy default).
|
||||
- "adaptive": returns round(max_tokens * recall_budget_adaptive_<level>),
|
||||
clamped to [recall_budget_min, recall_budget_max].
|
||||
|
||||
A None budget falls back to MID (preserves legacy default).
|
||||
"""
|
||||
effective_budget = budget if budget is not None else Budget.MID
|
||||
function = config_dict.get("recall_budget_function", "fixed")
|
||||
|
||||
if function == "adaptive":
|
||||
ratios = {
|
||||
Budget.LOW: config_dict.get("recall_budget_adaptive_low", 0.025),
|
||||
Budget.MID: config_dict.get("recall_budget_adaptive_mid", 0.075),
|
||||
Budget.HIGH: config_dict.get("recall_budget_adaptive_high", 0.25),
|
||||
}
|
||||
raw = round(max_tokens * float(ratios[effective_budget]))
|
||||
floor = int(config_dict.get("recall_budget_min", 20))
|
||||
ceiling = int(config_dict.get("recall_budget_max", 2000))
|
||||
return max(floor, min(ceiling, raw))
|
||||
|
||||
fixed = {
|
||||
Budget.LOW: config_dict.get("recall_budget_fixed_low", 100),
|
||||
Budget.MID: config_dict.get("recall_budget_fixed_mid", 300),
|
||||
Budget.HIGH: config_dict.get("recall_budget_fixed_high", 1000),
|
||||
}
|
||||
return int(fixed[effective_budget])
|
||||
|
||||
|
||||
def utcnow():
|
||||
"""Get current UTC time with timezone info."""
|
||||
return datetime.now(UTC)
|
||||
@@ -2520,10 +2553,11 @@ class MemoryEngine(MemoryEngineInterface):
|
||||
if result.tag_groups is not None:
|
||||
tag_groups = result.tag_groups
|
||||
|
||||
# Map budget enum to thinking_budget number (default to MID if None)
|
||||
budget_mapping = {Budget.LOW: 100, Budget.MID: 300, Budget.HIGH: 1000}
|
||||
effective_budget = budget if budget is not None else Budget.MID
|
||||
thinking_budget = budget_mapping[effective_budget]
|
||||
# Map budget enum to thinking_budget number using bank-resolved config.
|
||||
# Function "fixed" preserves legacy {LOW: 100, MID: 300, HIGH: 1000}; function "adaptive"
|
||||
# derives from max_tokens and clamps to [recall_budget_min, recall_budget_max].
|
||||
budget_config_dict = await self._config_resolver.get_bank_config(bank_id, request_context)
|
||||
thinking_budget = _resolve_thinking_budget(budget_config_dict, budget, max_tokens)
|
||||
|
||||
# Log recall start with tags if present (skip if quiet mode for internal operations)
|
||||
if not _quiet:
|
||||
@@ -2797,7 +2831,8 @@ class MemoryEngine(MemoryEngineInterface):
|
||||
|
||||
try:
|
||||
# Run optimized retrieval with connection budget
|
||||
config = get_config()
|
||||
# Resolve bank-specific config (supports per-bank RAG mode)
|
||||
config = await self._config_resolver.resolve_full_config(bank_id, request_context)
|
||||
effective_connection_budget = (
|
||||
connection_budget if connection_budget is not None else config.recall_connection_budget
|
||||
)
|
||||
@@ -2807,6 +2842,12 @@ class MemoryEngine(MemoryEngineInterface):
|
||||
) as op:
|
||||
budgeted_pool = op.wrap_pool(pool)
|
||||
parallel_start = time.time()
|
||||
# Pass False to skip temporal extraction entirely when
|
||||
# disabled via config. This avoids the ~120ms dateparser
|
||||
# overhead per recall.
|
||||
analyzer = self.query_analyzer if config.enable_temporal_extraction else False
|
||||
# Pass False to skip graph retrieval when disabled via config.
|
||||
graph = None if config.enable_graph_retrieval else False
|
||||
multi_result = await retrieve_all_fact_types_parallel(
|
||||
budgeted_pool,
|
||||
query,
|
||||
@@ -2815,7 +2856,8 @@ class MemoryEngine(MemoryEngineInterface):
|
||||
fact_type, # Pass all fact types at once
|
||||
thinking_budget,
|
||||
question_date,
|
||||
self.query_analyzer,
|
||||
analyzer,
|
||||
graph_retriever=graph,
|
||||
tags=tags,
|
||||
tags_match=tags_match,
|
||||
tag_groups=tag_groups,
|
||||
@@ -3049,47 +3091,62 @@ class MemoryEngine(MemoryEngineInterface):
|
||||
|
||||
# Step 4: Rerank using cross-encoder (MergedCandidate -> ScoredResult)
|
||||
step_start = time.time()
|
||||
reranker_instance = self._cross_encoder_reranker
|
||||
|
||||
rerank_span = tracer_otel.start_span("hindsight.recall_rerank")
|
||||
rerank_span.set_attribute("hindsight.bank_id", bank_id)
|
||||
rerank_span.set_attribute("hindsight.candidates_count", len(merged_candidates))
|
||||
|
||||
scored_results: list = []
|
||||
pre_filtered_count = 0
|
||||
try:
|
||||
# Ensure reranker is initialized (for lazy initialization mode)
|
||||
await reranker_instance.ensure_initialized()
|
||||
|
||||
# Pre-filter candidates to reduce reranking cost (RRF already provides good ranking)
|
||||
# This is especially important for remote rerankers with network latency
|
||||
reranker_max_candidates = get_config().reranker_max_candidates
|
||||
if len(merged_candidates) > reranker_max_candidates:
|
||||
# Sort by RRF score and take top candidates
|
||||
merged_candidates.sort(key=lambda mc: mc.rrf_score, reverse=True)
|
||||
pre_filtered_count = len(merged_candidates) - reranker_max_candidates
|
||||
merged_candidates = merged_candidates[:reranker_max_candidates]
|
||||
if config.enable_reranking:
|
||||
reranker_instance = self._cross_encoder_reranker
|
||||
|
||||
# Rerank using cross-encoder
|
||||
scored_results = await reranker_instance.rerank(query, merged_candidates)
|
||||
rerank_span = tracer_otel.start_span("hindsight.recall_rerank")
|
||||
rerank_span.set_attribute("hindsight.bank_id", bank_id)
|
||||
rerank_span.set_attribute("hindsight.candidates_count", len(merged_candidates))
|
||||
|
||||
try:
|
||||
# Ensure reranker is initialized (for lazy initialization mode)
|
||||
await reranker_instance.ensure_initialized()
|
||||
|
||||
# Pre-filter candidates to reduce reranking cost (RRF already provides good ranking)
|
||||
# This is especially important for remote rerankers with network latency
|
||||
reranker_max_candidates = get_config().reranker_max_candidates
|
||||
if len(merged_candidates) > reranker_max_candidates:
|
||||
# Sort by RRF score and take top candidates
|
||||
merged_candidates.sort(key=lambda mc: mc.rrf_score, reverse=True)
|
||||
pre_filtered_count = len(merged_candidates) - reranker_max_candidates
|
||||
merged_candidates = merged_candidates[:reranker_max_candidates]
|
||||
|
||||
# Rerank using cross-encoder
|
||||
scored_results = await reranker_instance.rerank(query, merged_candidates)
|
||||
|
||||
step_duration = time.time() - step_start
|
||||
pre_filter_note = f" (pre-filtered {pre_filtered_count})" if pre_filtered_count > 0 else ""
|
||||
log_buffer.append(
|
||||
f" [4] Reranking: {len(scored_results)} candidates scored in {step_duration:.3f}s{pre_filter_note}"
|
||||
)
|
||||
finally:
|
||||
rerank_span.set_attribute("hindsight.scored_count", len(scored_results))
|
||||
if pre_filtered_count > 0:
|
||||
rerank_span.set_attribute("hindsight.pre_filtered_count", pre_filtered_count)
|
||||
rerank_span.end()
|
||||
|
||||
# Step 4.5: Combine cross-encoder score with retrieval signals via multiplicative boosts.
|
||||
# See apply_combined_scoring for the full rationale and formula.
|
||||
if scored_results:
|
||||
apply_combined_scoring(scored_results, now=utcnow())
|
||||
scored_results.sort(key=lambda x: x.weight, reverse=True)
|
||||
log_buffer.append(" [4.6] Combined scoring: ce * recency_boost(0.2) * temporal_boost(0.2)")
|
||||
else:
|
||||
# Reranking disabled — use RRF scores directly
|
||||
from .search.types import ScoredResult
|
||||
merged_candidates.sort(key=lambda mc: mc.rrf_score, reverse=True)
|
||||
scored_results = [
|
||||
ScoredResult(candidate=mc, weight=mc.rrf_score)
|
||||
for mc in merged_candidates
|
||||
]
|
||||
step_duration = time.time() - step_start
|
||||
pre_filter_note = f" (pre-filtered {pre_filtered_count})" if pre_filtered_count > 0 else ""
|
||||
log_buffer.append(
|
||||
f" [4] Reranking: {len(scored_results)} candidates scored in {step_duration:.3f}s{pre_filter_note}"
|
||||
f" [4] Reranking: skipped ({len(scored_results)} candidates ranked by RRF in {step_duration:.3f}s)"
|
||||
)
|
||||
finally:
|
||||
rerank_span.set_attribute("hindsight.scored_count", len(scored_results))
|
||||
if pre_filtered_count > 0:
|
||||
rerank_span.set_attribute("hindsight.pre_filtered_count", pre_filtered_count)
|
||||
rerank_span.end()
|
||||
|
||||
# Step 4.5: Combine cross-encoder score with retrieval signals via multiplicative boosts.
|
||||
# See apply_combined_scoring for the full rationale and formula.
|
||||
if scored_results:
|
||||
apply_combined_scoring(scored_results, now=utcnow())
|
||||
scored_results.sort(key=lambda x: x.weight, reverse=True)
|
||||
log_buffer.append(" [4.6] Combined scoring: ce * recency_boost(0.2) * temporal_boost(0.2)")
|
||||
|
||||
# Add reranked results to tracer AFTER combined scoring (so normalized values are included)
|
||||
if tracer:
|
||||
|
||||
@@ -561,16 +561,23 @@ async def retrieve_all_fact_types_parallel(
|
||||
"""
|
||||
import time
|
||||
|
||||
retriever = graph_retriever or get_default_graph_retriever()
|
||||
skip_graph = graph_retriever is False
|
||||
retriever = None if skip_graph else (graph_retriever or get_default_graph_retriever())
|
||||
start_time = time.time()
|
||||
timings: dict[str, float] = {}
|
||||
|
||||
# Step 1: Extract temporal constraint first (CPU work, no DB)
|
||||
# Do this before DB queries so we know if we need temporal retrieval
|
||||
# Do this before DB queries so we know if we need temporal retrieval.
|
||||
# Skip entirely when query_analyzer is False (temporal extraction disabled
|
||||
# via HINDSIGHT_API_ENABLE_TEMPORAL_EXTRACTION=false). This saves ~120ms
|
||||
# per recall by avoiding the dateparser library.
|
||||
temporal_extraction_start = time.time()
|
||||
from .temporal_extraction import extract_temporal_constraint
|
||||
if query_analyzer is not False:
|
||||
from .temporal_extraction import extract_temporal_constraint
|
||||
|
||||
temporal_constraint = extract_temporal_constraint(query_text, reference_date=question_date, analyzer=query_analyzer)
|
||||
temporal_constraint = extract_temporal_constraint(query_text, reference_date=question_date, analyzer=query_analyzer)
|
||||
else:
|
||||
temporal_constraint = None
|
||||
temporal_extraction_time = time.time() - temporal_extraction_start
|
||||
timings["temporal_extraction"] = temporal_extraction_time
|
||||
|
||||
@@ -639,9 +646,12 @@ async def retrieve_all_fact_types_parallel(
|
||||
)
|
||||
return ft, results, time.time() - graph_start, graph_timing
|
||||
|
||||
# Run graph for all fact types in parallel
|
||||
graph_tasks = [run_graph_for_fact_type(ft) for ft in fact_types]
|
||||
graph_results_list = await asyncio.gather(*graph_tasks)
|
||||
# Run graph for all fact types in parallel (skip when disabled)
|
||||
if skip_graph:
|
||||
graph_results_list = []
|
||||
else:
|
||||
graph_tasks = [run_graph_for_fact_type(ft) for ft in fact_types]
|
||||
graph_results_list = await asyncio.gather(*graph_tasks)
|
||||
|
||||
# Organize results by fact type
|
||||
results_by_fact_type: dict[str, ParallelRetrievalResult] = {}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
"""Verify that BankTemplateConfig exposes every hierarchical field that
|
||||
_CONFIGURABLE_FIELDS already accepts at the engine layer.
|
||||
|
||||
This test guards the fix for the gap described in the upstream PR title
|
||||
"fix(bank-template): align BankTemplateConfig with _CONFIGURABLE_FIELDS".
|
||||
Each new field is POSTed through /v1/default/banks/{id}/import and then
|
||||
read back via the bank-config endpoint; assertion is that the applied
|
||||
value round-trips through the engine.
|
||||
|
||||
Runs via: uv run pytest tests/test_bank_template_configurable_fields.py -v
|
||||
|
||||
The api_client fixture (shared with tests/test_bank_templates.py) wraps
|
||||
create_app(memory, initialize_memory=False) in an httpx.ASGITransport
|
||||
with base_url http://test — in-process, no network, no tenant extension.
|
||||
Copy the fixture inline here so the test file does not depend on a
|
||||
conftest we do not ship in the patch.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from hindsight_api.api import create_app
|
||||
from hindsight_api.api.http import BankTemplateConfig
|
||||
|
||||
# Each tuple is (field_name, applied_value). Values chosen to differ
|
||||
# visibly from defaults so round-trip bugs surface.
|
||||
NEW_FIELDS: list[tuple[str, object]] = [
|
||||
("retain_default_strategy", "strategy-a"),
|
||||
("retain_strategies", {"strategy-a": {"mode": "concise", "max_tokens": 512}}),
|
||||
("retain_chunk_batch_size", 7),
|
||||
("mcp_enabled_tools", ["list_banks", "get_bank_profile"]),
|
||||
("consolidation_llm_batch_size", 11),
|
||||
("consolidation_source_facts_max_tokens", 2048),
|
||||
("consolidation_source_facts_max_tokens_per_observation", 256),
|
||||
("max_observations_per_scope", 13),
|
||||
("reflect_source_facts_max_tokens", 4096),
|
||||
("llm_gemini_safety_settings", [{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"}]),
|
||||
("recall_budget_function", "adaptive"),
|
||||
("recall_budget_fixed_low", 50),
|
||||
("recall_budget_fixed_mid", 250),
|
||||
("recall_budget_fixed_high", 800),
|
||||
("recall_budget_adaptive_low", 0.05),
|
||||
("recall_budget_adaptive_mid", 0.1),
|
||||
("recall_budget_adaptive_high", 0.4),
|
||||
("recall_budget_min", 30),
|
||||
("recall_budget_max", 1500),
|
||||
]
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def api_client(memory):
|
||||
"""Matches the fixture in tests/test_bank_templates.py — in-process
|
||||
ASGI test client, no tenant extension, no auth."""
|
||||
app = create_app(memory, initialize_memory=False)
|
||||
transport = httpx.ASGITransport(app=app)
|
||||
async with httpx.AsyncClient(transport=transport, base_url="http://test") as client:
|
||||
yield client
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def bank_id():
|
||||
return f"tmpl_config_{datetime.now().timestamp()}"
|
||||
|
||||
|
||||
def test_bank_template_config_declares_every_configurable_field():
|
||||
"""Pydantic-level guard: every field in NEW_FIELDS must be a declared
|
||||
attribute of BankTemplateConfig so get_config_updates() picks it up."""
|
||||
declared = set(BankTemplateConfig.model_fields.keys())
|
||||
missing = [name for name, _ in NEW_FIELDS if name not in declared]
|
||||
assert not missing, f"BankTemplateConfig missing fields: {missing}"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize("field_name,applied_value", NEW_FIELDS, ids=[n for n, _ in NEW_FIELDS])
|
||||
async def test_new_field_round_trips_through_import(
|
||||
api_client: httpx.AsyncClient,
|
||||
bank_id: str,
|
||||
field_name: str,
|
||||
applied_value: object,
|
||||
):
|
||||
"""POST a minimal manifest with one new field set, then read bank
|
||||
config back and assert the value made it through.
|
||||
|
||||
Bank config response shape per upstream's test_import_applies_config:
|
||||
top-level keys are resolved hierarchical config; per-bank overrides
|
||||
live under config["overrides"][<field>]. Assert on the override slot.
|
||||
"""
|
||||
unique_bank_id = f"{bank_id}_{field_name}"
|
||||
manifest = {
|
||||
"version": "1",
|
||||
"bank": {field_name: applied_value},
|
||||
}
|
||||
|
||||
resp = await api_client.post(
|
||||
f"/v1/default/banks/{unique_bank_id}/import",
|
||||
json=manifest,
|
||||
)
|
||||
assert resp.status_code == 200, resp.text
|
||||
|
||||
# Read bank config back — field must reflect the applied value
|
||||
# under the "overrides" slot, matching upstream's own test shape.
|
||||
read = await api_client.get(f"/v1/default/banks/{unique_bank_id}/config")
|
||||
assert read.status_code == 200, read.text
|
||||
config = read.json()
|
||||
overrides = config.get("overrides", {})
|
||||
assert overrides.get(field_name) == applied_value, (
|
||||
f"round-trip mismatch for {field_name}: "
|
||||
f"sent {applied_value!r}, got {overrides.get(field_name)!r} "
|
||||
f"(full overrides: {overrides!r})"
|
||||
)
|
||||
@@ -96,9 +96,12 @@ async def test_hierarchical_fields_categorization():
|
||||
assert "llm_gemini_safety_settings" in configurable
|
||||
assert "mcp_enabled_tools" in configurable
|
||||
assert "retain_chunk_batch_size" in configurable
|
||||
assert "enable_temporal_extraction" in configurable
|
||||
assert "enable_graph_retrieval" in configurable
|
||||
assert "enable_reranking" in configurable
|
||||
|
||||
# Verify count is correct
|
||||
assert len(configurable) == 22
|
||||
assert len(configurable) == 34
|
||||
|
||||
# Verify credential fields (NEVER exposed)
|
||||
assert "llm_api_key" in credentials
|
||||
@@ -411,7 +414,7 @@ async def test_config_get_bank_config_no_static_or_credential_fields_leak(memory
|
||||
assert field in config, f"Expected configurable field '{field}' missing from config"
|
||||
|
||||
# Should have a small number of configurable fields (not hundreds)
|
||||
assert len(config) < 25, f"Too many fields returned: {len(config)}"
|
||||
assert len(config) < 50, f"Too many fields returned: {len(config)}"
|
||||
|
||||
finally:
|
||||
await memory.delete_bank(bank_id, request_context=request_context)
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
"""
|
||||
Tests for the configurable recall-budget mapping (Budget enum -> thinking_budget int).
|
||||
|
||||
Two functions are supported:
|
||||
- "fixed": returns the recall_budget_fixed_<level> integer directly (legacy default).
|
||||
- "adaptive": returns round(max_tokens * recall_budget_adaptive_<level>),
|
||||
clamped to [recall_budget_min, recall_budget_max].
|
||||
|
||||
Both the function selector and the per-level numbers are hierarchical config
|
||||
fields (global env -> tenant -> bank), so they can be overridden per bank.
|
||||
"""
|
||||
|
||||
import dataclasses
|
||||
|
||||
import pytest
|
||||
|
||||
from hindsight_api.config import (
|
||||
DEFAULT_RECALL_BUDGET_ADAPTIVE_HIGH,
|
||||
DEFAULT_RECALL_BUDGET_ADAPTIVE_LOW,
|
||||
DEFAULT_RECALL_BUDGET_ADAPTIVE_MID,
|
||||
DEFAULT_RECALL_BUDGET_FIXED_HIGH,
|
||||
DEFAULT_RECALL_BUDGET_FIXED_LOW,
|
||||
DEFAULT_RECALL_BUDGET_FIXED_MID,
|
||||
DEFAULT_RECALL_BUDGET_MAX,
|
||||
DEFAULT_RECALL_BUDGET_MIN,
|
||||
DEFAULT_RECALL_BUDGET_FUNCTION,
|
||||
ENV_RECALL_BUDGET_ADAPTIVE_LOW,
|
||||
ENV_RECALL_BUDGET_ADAPTIVE_MID,
|
||||
ENV_RECALL_BUDGET_FIXED_HIGH,
|
||||
ENV_RECALL_BUDGET_FIXED_LOW,
|
||||
ENV_RECALL_BUDGET_FIXED_MID,
|
||||
ENV_RECALL_BUDGET_MAX,
|
||||
ENV_RECALL_BUDGET_MIN,
|
||||
ENV_RECALL_BUDGET_FUNCTION,
|
||||
RECALL_BUDGET_FUNCTIONS,
|
||||
HindsightConfig,
|
||||
)
|
||||
from hindsight_api.config_resolver import _validate_recall_budget_updates
|
||||
from hindsight_api.engine.memory_engine import Budget, _resolve_thinking_budget
|
||||
|
||||
|
||||
_BUDGET_FIELD_NAMES = (
|
||||
"recall_budget_function",
|
||||
"recall_budget_fixed_low",
|
||||
"recall_budget_fixed_mid",
|
||||
"recall_budget_fixed_high",
|
||||
"recall_budget_adaptive_low",
|
||||
"recall_budget_adaptive_mid",
|
||||
"recall_budget_adaptive_high",
|
||||
"recall_budget_min",
|
||||
"recall_budget_max",
|
||||
)
|
||||
|
||||
|
||||
class TestBudgetConfigFields:
|
||||
def test_fields_exist_on_dataclass(self):
|
||||
names = {f.name for f in dataclasses.fields(HindsightConfig)}
|
||||
for field_name in _BUDGET_FIELD_NAMES:
|
||||
assert field_name in names, f"Missing dataclass field: {field_name}"
|
||||
|
||||
def test_fields_are_configurable(self):
|
||||
configurable = HindsightConfig.get_configurable_fields()
|
||||
for field_name in _BUDGET_FIELD_NAMES:
|
||||
assert field_name in configurable, f"Field not in _CONFIGURABLE_FIELDS: {field_name}"
|
||||
|
||||
def test_default_function_is_fixed_for_backwards_compat(self):
|
||||
# The whole point of function="fixed" being default is to preserve legacy behavior.
|
||||
assert DEFAULT_RECALL_BUDGET_FUNCTION == "fixed"
|
||||
assert "fixed" in RECALL_BUDGET_FUNCTIONS
|
||||
assert "adaptive" in RECALL_BUDGET_FUNCTIONS
|
||||
|
||||
def test_default_fixed_values_match_legacy_hardcoded_mapping(self):
|
||||
# These are the values that used to live in the hardcoded budget_mapping dict.
|
||||
assert DEFAULT_RECALL_BUDGET_FIXED_LOW == 100
|
||||
assert DEFAULT_RECALL_BUDGET_FIXED_MID == 300
|
||||
assert DEFAULT_RECALL_BUDGET_FIXED_HIGH == 1000
|
||||
|
||||
def test_default_adaptive_clamps_are_sane(self):
|
||||
assert DEFAULT_RECALL_BUDGET_MIN >= 1
|
||||
assert DEFAULT_RECALL_BUDGET_MAX > DEFAULT_RECALL_BUDGET_MIN
|
||||
|
||||
def test_env_var_constants(self):
|
||||
assert ENV_RECALL_BUDGET_FUNCTION == "HINDSIGHT_API_RECALL_BUDGET_FUNCTION"
|
||||
assert ENV_RECALL_BUDGET_FIXED_LOW == "HINDSIGHT_API_RECALL_BUDGET_FIXED_LOW"
|
||||
assert ENV_RECALL_BUDGET_FIXED_MID == "HINDSIGHT_API_RECALL_BUDGET_FIXED_MID"
|
||||
assert ENV_RECALL_BUDGET_FIXED_HIGH == "HINDSIGHT_API_RECALL_BUDGET_FIXED_HIGH"
|
||||
assert ENV_RECALL_BUDGET_ADAPTIVE_LOW == "HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_LOW"
|
||||
assert ENV_RECALL_BUDGET_ADAPTIVE_MID == "HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_MID"
|
||||
assert ENV_RECALL_BUDGET_MIN == "HINDSIGHT_API_RECALL_BUDGET_MIN"
|
||||
assert ENV_RECALL_BUDGET_MAX == "HINDSIGHT_API_RECALL_BUDGET_MAX"
|
||||
|
||||
def test_from_env_reads_overrides(self, monkeypatch):
|
||||
monkeypatch.setenv(ENV_RECALL_BUDGET_FUNCTION, "adaptive")
|
||||
monkeypatch.setenv(ENV_RECALL_BUDGET_FIXED_MID, "777")
|
||||
monkeypatch.setenv(ENV_RECALL_BUDGET_ADAPTIVE_MID, "0.5")
|
||||
monkeypatch.setenv(ENV_RECALL_BUDGET_MIN, "5")
|
||||
monkeypatch.setenv(ENV_RECALL_BUDGET_MAX, "9999")
|
||||
|
||||
config = HindsightConfig.from_env()
|
||||
assert config.recall_budget_function == "adaptive"
|
||||
assert config.recall_budget_fixed_mid == 777
|
||||
assert config.recall_budget_adaptive_mid == 0.5
|
||||
assert config.recall_budget_min == 5
|
||||
assert config.recall_budget_max == 9999
|
||||
|
||||
def test_from_env_invalid_function_falls_back_to_default(self, monkeypatch):
|
||||
# Defensive parsing: an invalid env value logs a warning and falls back.
|
||||
monkeypatch.setenv(ENV_RECALL_BUDGET_FUNCTION, "garbage")
|
||||
config = HindsightConfig.from_env()
|
||||
assert config.recall_budget_function == DEFAULT_RECALL_BUDGET_FUNCTION
|
||||
|
||||
|
||||
class TestResolveThinkingBudgetFixedFunction:
|
||||
@pytest.fixture
|
||||
def fixed_config(self):
|
||||
return {
|
||||
"recall_budget_function": "fixed",
|
||||
"recall_budget_fixed_low": 100,
|
||||
"recall_budget_fixed_mid": 300,
|
||||
"recall_budget_fixed_high": 1000,
|
||||
"recall_budget_adaptive_low": 0.025,
|
||||
"recall_budget_adaptive_mid": 0.075,
|
||||
"recall_budget_adaptive_high": 0.25,
|
||||
"recall_budget_min": 20,
|
||||
"recall_budget_max": 2000,
|
||||
}
|
||||
|
||||
def test_low_mid_high_match_fixed_values(self, fixed_config):
|
||||
assert _resolve_thinking_budget(fixed_config, Budget.LOW, 4096) == 100
|
||||
assert _resolve_thinking_budget(fixed_config, Budget.MID, 4096) == 300
|
||||
assert _resolve_thinking_budget(fixed_config, Budget.HIGH, 4096) == 1000
|
||||
|
||||
def test_none_budget_defaults_to_mid(self, fixed_config):
|
||||
assert _resolve_thinking_budget(fixed_config, None, 4096) == 300
|
||||
|
||||
def test_max_tokens_does_not_affect_fixed_function(self, fixed_config):
|
||||
# Whole point of "fixed": result is independent of max_tokens.
|
||||
assert _resolve_thinking_budget(fixed_config, Budget.MID, 1) == 300
|
||||
assert _resolve_thinking_budget(fixed_config, Budget.MID, 1_000_000) == 300
|
||||
|
||||
def test_per_bank_overrides_take_effect(self, fixed_config):
|
||||
fixed_config["recall_budget_fixed_mid"] = 42
|
||||
assert _resolve_thinking_budget(fixed_config, Budget.MID, 4096) == 42
|
||||
|
||||
|
||||
class TestResolveThinkingBudgetAdaptiveFunction:
|
||||
@pytest.fixture
|
||||
def adaptive_config(self):
|
||||
return {
|
||||
"recall_budget_function": "adaptive",
|
||||
"recall_budget_fixed_low": 100,
|
||||
"recall_budget_fixed_mid": 300,
|
||||
"recall_budget_fixed_high": 1000,
|
||||
"recall_budget_adaptive_low": 0.025,
|
||||
"recall_budget_adaptive_mid": 0.075,
|
||||
"recall_budget_adaptive_high": 0.25,
|
||||
"recall_budget_min": 20,
|
||||
"recall_budget_max": 2000,
|
||||
}
|
||||
|
||||
def test_scales_with_max_tokens(self, adaptive_config):
|
||||
# 4096 * 0.075 = 307.2 -> 307
|
||||
assert _resolve_thinking_budget(adaptive_config, Budget.MID, 4096) == 307
|
||||
# 8192 * 0.075 = 614.4 -> 614
|
||||
assert _resolve_thinking_budget(adaptive_config, Budget.MID, 8192) == 614
|
||||
|
||||
def test_clamps_to_floor_when_max_tokens_tiny(self, adaptive_config):
|
||||
# 100 * 0.025 = 2.5 -> 2 -> clamped to floor 20
|
||||
assert _resolve_thinking_budget(adaptive_config, Budget.LOW, 100) == 20
|
||||
|
||||
def test_clamps_to_ceiling_when_max_tokens_huge(self, adaptive_config):
|
||||
# 100_000 * 0.25 = 25_000 -> clamped to ceiling 2000
|
||||
assert _resolve_thinking_budget(adaptive_config, Budget.HIGH, 100_000) == 2000
|
||||
|
||||
def test_none_budget_defaults_to_mid(self, adaptive_config):
|
||||
assert _resolve_thinking_budget(adaptive_config, None, 4096) == 307
|
||||
|
||||
def test_custom_clamps_per_bank(self, adaptive_config):
|
||||
adaptive_config["recall_budget_min"] = 500
|
||||
adaptive_config["recall_budget_max"] = 600
|
||||
# 4096 * 0.075 = 307 -> below floor 500
|
||||
assert _resolve_thinking_budget(adaptive_config, Budget.MID, 4096) == 500
|
||||
# 4096 * 0.25 = 1024 -> above ceiling 600
|
||||
assert _resolve_thinking_budget(adaptive_config, Budget.HIGH, 4096) == 600
|
||||
|
||||
|
||||
class TestResolveThinkingBudgetFallbacks:
|
||||
def test_empty_config_uses_legacy_defaults(self):
|
||||
# Resilience: missing keys should not crash; fallback to legacy mapping.
|
||||
assert _resolve_thinking_budget({}, Budget.LOW, 4096) == 100
|
||||
assert _resolve_thinking_budget({}, Budget.MID, 4096) == 300
|
||||
assert _resolve_thinking_budget({}, Budget.HIGH, 4096) == 1000
|
||||
|
||||
def test_unknown_function_falls_back_to_fixed(self):
|
||||
# Defensive: if some bad config slipped past validation, behave like "fixed".
|
||||
assert _resolve_thinking_budget({"recall_budget_function": "garbage"}, Budget.MID, 4096) == 300
|
||||
|
||||
|
||||
class TestValidateRecallBudgetUpdates:
|
||||
def test_no_op_passes(self):
|
||||
_validate_recall_budget_updates({})
|
||||
_validate_recall_budget_updates({"unrelated_field": 123})
|
||||
|
||||
def test_valid_function_values(self):
|
||||
_validate_recall_budget_updates({"recall_budget_function": "fixed"})
|
||||
_validate_recall_budget_updates({"recall_budget_function": "adaptive"})
|
||||
|
||||
def test_invalid_function_raises(self):
|
||||
with pytest.raises(ValueError, match="recall_budget_function"):
|
||||
_validate_recall_budget_updates({"recall_budget_function": "wrong"})
|
||||
with pytest.raises(ValueError, match="recall_budget_function"):
|
||||
_validate_recall_budget_updates({"recall_budget_function": 123})
|
||||
|
||||
def test_fixed_must_be_positive_integer(self):
|
||||
for key in ("recall_budget_fixed_low", "recall_budget_fixed_mid", "recall_budget_fixed_high"):
|
||||
_validate_recall_budget_updates({key: 1})
|
||||
_validate_recall_budget_updates({key: 100_000})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: 0})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: -5})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: 1.5}) # float not allowed for fixed
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: True}) # bool sneaks past int check
|
||||
|
||||
def test_adaptive_must_be_positive_number(self):
|
||||
for key in ("recall_budget_adaptive_low", "recall_budget_adaptive_mid", "recall_budget_adaptive_high"):
|
||||
_validate_recall_budget_updates({key: 0.001})
|
||||
_validate_recall_budget_updates({key: 1.0})
|
||||
_validate_recall_budget_updates({key: 5}) # int is acceptable as a number
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: 0})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: -0.1})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: True})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: "0.5"})
|
||||
|
||||
def test_min_must_be_le_max_when_both_set(self):
|
||||
_validate_recall_budget_updates({"recall_budget_min": 10, "recall_budget_max": 1000})
|
||||
_validate_recall_budget_updates({"recall_budget_min": 100, "recall_budget_max": 100})
|
||||
with pytest.raises(ValueError, match="recall_budget_min"):
|
||||
_validate_recall_budget_updates({"recall_budget_min": 5000, "recall_budget_max": 100})
|
||||
|
||||
def test_min_max_must_be_positive_integers(self):
|
||||
for key in ("recall_budget_min", "recall_budget_max"):
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: 0})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: -1})
|
||||
with pytest.raises(ValueError, match=key):
|
||||
_validate_recall_budget_updates({key: 1.5})
|
||||
@@ -0,0 +1,463 @@
|
||||
"""
|
||||
Tests for RAG mode config flags: temporal extraction and graph retrieval.
|
||||
|
||||
Verifies that:
|
||||
1. Config flags default to True (full retrieval pipeline).
|
||||
2. Disabling temporal extraction skips dateparser and temporal DB queries.
|
||||
3. Disabling graph retrieval skips entity/link traversal.
|
||||
4. Recall still returns relevant results with both disabled (2-way: semantic + BM25).
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
|
||||
from hindsight_api import LocalSTEmbeddings, MemoryEngine, RequestContext
|
||||
from hindsight_api.engine.cross_encoder import LocalSTCrossEncoder
|
||||
from hindsight_api.engine.memory_engine import Budget
|
||||
from hindsight_api.engine.query_analyzer import DateparserQueryAnalyzer
|
||||
from hindsight_api.engine.task_backend import SyncTaskBackend
|
||||
from hindsight_api.config import (
|
||||
ENV_ENABLE_TEMPORAL_EXTRACTION,
|
||||
DEFAULT_ENABLE_TEMPORAL_EXTRACTION,
|
||||
ENV_ENABLE_GRAPH_RETRIEVAL,
|
||||
DEFAULT_ENABLE_GRAPH_RETRIEVAL,
|
||||
clear_config_cache,
|
||||
HindsightConfig,
|
||||
)
|
||||
|
||||
# Env vars managed by the clean_env fixture
|
||||
_MANAGED_ENV_VARS = [ENV_ENABLE_TEMPORAL_EXTRACTION, ENV_ENABLE_GRAPH_RETRIEVAL]
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def clean_env():
|
||||
"""Save and restore RAG mode env vars around each test."""
|
||||
originals = {k: os.environ.get(k) for k in _MANAGED_ENV_VARS}
|
||||
clear_config_cache()
|
||||
yield
|
||||
for k, v in originals.items():
|
||||
if v is None:
|
||||
os.environ.pop(k, None)
|
||||
else:
|
||||
os.environ[k] = v
|
||||
clear_config_cache()
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(scope="function")
|
||||
async def none_memory(pg0_db_url, embeddings, cross_encoder, query_analyzer):
|
||||
"""MemoryEngine with provider=none (chunks mode — no LLM needed for retain)."""
|
||||
mem = MemoryEngine(
|
||||
db_url=pg0_db_url,
|
||||
memory_llm_provider="none",
|
||||
memory_llm_api_key=None,
|
||||
memory_llm_model="none",
|
||||
embeddings=embeddings,
|
||||
cross_encoder=cross_encoder,
|
||||
query_analyzer=query_analyzer,
|
||||
pool_min_size=1,
|
||||
pool_max_size=5,
|
||||
run_migrations=False,
|
||||
task_backend=SyncTaskBackend(),
|
||||
)
|
||||
await mem.initialize()
|
||||
yield mem
|
||||
try:
|
||||
if mem._pool and not mem._pool._closing:
|
||||
await mem.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Config-level tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_temporal_extraction_defaults_to_true():
|
||||
"""Default value should be True (temporal extraction on)."""
|
||||
assert DEFAULT_ENABLE_TEMPORAL_EXTRACTION is True
|
||||
|
||||
|
||||
def test_config_enables_temporal_extraction_by_default():
|
||||
"""HindsightConfig.from_env() should set enable_temporal_extraction=True when env var is unset."""
|
||||
os.environ.pop(ENV_ENABLE_TEMPORAL_EXTRACTION, None)
|
||||
os.environ.setdefault("HINDSIGHT_API_LLM_PROVIDER", "mock")
|
||||
config = HindsightConfig.from_env()
|
||||
assert config.enable_temporal_extraction is True
|
||||
|
||||
|
||||
def test_config_disables_temporal_extraction_when_false():
|
||||
"""Setting the env var to 'false' should disable temporal extraction."""
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
os.environ.setdefault("HINDSIGHT_API_LLM_PROVIDER", "mock")
|
||||
config = HindsightConfig.from_env()
|
||||
assert config.enable_temporal_extraction is False
|
||||
|
||||
|
||||
def test_config_enables_temporal_extraction_when_true():
|
||||
"""Setting the env var to 'true' explicitly should enable it."""
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "true"
|
||||
os.environ.setdefault("HINDSIGHT_API_LLM_PROVIDER", "mock")
|
||||
config = HindsightConfig.from_env()
|
||||
assert config.enable_temporal_extraction is True
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Integration tests — full retain + recall with temporal extraction on/off
|
||||
# Uses provider=none so retain works in chunks mode (no LLM needed).
|
||||
# Recall finds chunks via semantic search (embeddings only).
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_recall_returns_results_with_temporal_extraction_enabled(none_memory, request_context):
|
||||
"""
|
||||
With temporal extraction enabled (default), recall should return results
|
||||
for a query that contains temporal language.
|
||||
"""
|
||||
os.environ.pop(ENV_ENABLE_TEMPORAL_EXTRACTION, None)
|
||||
clear_config_cache()
|
||||
|
||||
bank_id = f"test_temporal_enabled_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await none_memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="In March 2024, the team shipped the new authentication system. It replaced the legacy OAuth flow.",
|
||||
context="engineering update",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
result = await none_memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query="What happened with authentication in March 2024?",
|
||||
budget=Budget.LOW,
|
||||
include_chunks=True,
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
has_results = len(result.results) > 0 or (result.chunks is not None and len(result.chunks) > 0)
|
||||
assert has_results, "Should find results with temporal extraction enabled"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_recall_returns_results_with_temporal_extraction_disabled(none_memory, request_context):
|
||||
"""
|
||||
With temporal extraction disabled, recall should still return results
|
||||
via semantic + BM25 + graph retrieval (3-way).
|
||||
"""
|
||||
bank_id = f"test_temporal_disabled_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await none_memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="In March 2024, the team shipped the new authentication system. It replaced the legacy OAuth flow.",
|
||||
context="engineering update",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
# Now disable temporal extraction for recall
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
clear_config_cache()
|
||||
|
||||
result = await none_memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query="What happened with authentication in March 2024?",
|
||||
budget=Budget.LOW,
|
||||
include_chunks=True,
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
has_results = len(result.results) > 0 or (result.chunks is not None and len(result.chunks) > 0)
|
||||
assert has_results, "Should find results even with temporal extraction disabled (3-way retrieval)"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_recall_non_temporal_query_works_with_extraction_disabled(none_memory, request_context):
|
||||
"""
|
||||
A non-temporal query should work with temporal extraction disabled.
|
||||
"""
|
||||
bank_id = f"test_non_temporal_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await none_memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="Alice is a software engineer who specializes in distributed systems and Kubernetes.",
|
||||
context="team info",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
# Disable temporal extraction
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
clear_config_cache()
|
||||
|
||||
result = await none_memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query="Who is Alice?",
|
||||
budget=Budget.LOW,
|
||||
include_chunks=True,
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
has_results = len(result.results) > 0 or (result.chunks is not None and len(result.chunks) > 0)
|
||||
assert has_results, "Should find results for non-temporal query"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_recall_latency_lower_with_temporal_extraction_disabled(none_memory, request_context):
|
||||
"""
|
||||
Recall with temporal extraction disabled should be measurably faster
|
||||
than with it enabled, since we skip the dateparser overhead.
|
||||
"""
|
||||
bank_id = f"test_latency_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await none_memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="The quarterly revenue report showed strong growth in Q3 2024.",
|
||||
context="business update",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
query = "What was the revenue in Q3 2024?"
|
||||
|
||||
# Measure with temporal extraction enabled
|
||||
os.environ.pop(ENV_ENABLE_TEMPORAL_EXTRACTION, None)
|
||||
clear_config_cache()
|
||||
|
||||
enabled_times = []
|
||||
for _ in range(3):
|
||||
start = time.perf_counter()
|
||||
await none_memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query=query,
|
||||
budget=Budget.LOW,
|
||||
request_context=request_context,
|
||||
)
|
||||
enabled_times.append((time.perf_counter() - start) * 1000)
|
||||
|
||||
# Measure with temporal extraction disabled
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
clear_config_cache()
|
||||
|
||||
disabled_times = []
|
||||
for _ in range(3):
|
||||
start = time.perf_counter()
|
||||
await none_memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query=query,
|
||||
budget=Budget.LOW,
|
||||
request_context=request_context,
|
||||
)
|
||||
disabled_times.append((time.perf_counter() - start) * 1000)
|
||||
|
||||
enabled_avg = sum(enabled_times) / len(enabled_times)
|
||||
disabled_avg = sum(disabled_times) / len(disabled_times)
|
||||
|
||||
print(f"\n Enabled avg: {enabled_avg:.1f}ms")
|
||||
print(f" Disabled avg: {disabled_avg:.1f}ms")
|
||||
print(f" Savings: {enabled_avg - disabled_avg:.1f}ms")
|
||||
|
||||
# Disabled should be faster
|
||||
assert disabled_avg < enabled_avg, (
|
||||
f"Expected disabled ({disabled_avg:.1f}ms) to be faster than enabled ({enabled_avg:.1f}ms)"
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Integration tests with real LLM — retains extract facts, recall searches them.
|
||||
# These require HINDSIGHT_API_LLM_API_KEY in the environment (available in CI).
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_llm_recall_with_temporal_extraction_enabled(memory, request_context):
|
||||
"""
|
||||
With a real LLM: retain extracts facts, recall finds them with temporal
|
||||
extraction enabled (4-way retrieval).
|
||||
"""
|
||||
os.environ.pop(ENV_ENABLE_TEMPORAL_EXTRACTION, None)
|
||||
clear_config_cache()
|
||||
|
||||
bank_id = f"test_llm_temporal_on_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="In March 2024, the team shipped the new authentication system. It replaced the legacy OAuth flow with OIDC.",
|
||||
context="engineering update",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
result = await memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query="What happened with authentication in March 2024?",
|
||||
budget=Budget.LOW,
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
assert len(result.results) > 0, "Should find facts with temporal extraction enabled"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_llm_recall_with_temporal_extraction_disabled(memory, request_context):
|
||||
"""
|
||||
With a real LLM: retain extracts facts, recall finds them with temporal
|
||||
extraction disabled (3-way retrieval — semantic + BM25 + graph).
|
||||
"""
|
||||
bank_id = f"test_llm_temporal_off_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="In March 2024, the team shipped the new authentication system. It replaced the legacy OAuth flow with OIDC.",
|
||||
context="engineering update",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
# Disable temporal extraction for recall
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
clear_config_cache()
|
||||
|
||||
result = await memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query="What happened with authentication in March 2024?",
|
||||
budget=Budget.LOW,
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
assert len(result.results) > 0, "Should find facts even with temporal extraction disabled (3-way retrieval)"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_llm_recall_latency_comparison(memory, request_context):
|
||||
"""
|
||||
With a real LLM: measure recall latency with temporal extraction on vs off.
|
||||
"""
|
||||
bank_id = f"test_llm_latency_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="The quarterly revenue report showed strong growth in Q3 2024. Revenue increased 15% year over year.",
|
||||
context="business update",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
query = "What was the revenue in Q3 2024?"
|
||||
|
||||
# Measure with temporal extraction enabled
|
||||
os.environ.pop(ENV_ENABLE_TEMPORAL_EXTRACTION, None)
|
||||
clear_config_cache()
|
||||
|
||||
enabled_times = []
|
||||
for _ in range(3):
|
||||
start = time.perf_counter()
|
||||
await memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query=query,
|
||||
budget=Budget.LOW,
|
||||
request_context=request_context,
|
||||
)
|
||||
enabled_times.append((time.perf_counter() - start) * 1000)
|
||||
|
||||
# Measure with temporal extraction disabled
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
clear_config_cache()
|
||||
|
||||
disabled_times = []
|
||||
for _ in range(3):
|
||||
start = time.perf_counter()
|
||||
await memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query=query,
|
||||
budget=Budget.LOW,
|
||||
request_context=request_context,
|
||||
)
|
||||
disabled_times.append((time.perf_counter() - start) * 1000)
|
||||
|
||||
enabled_avg = sum(enabled_times) / len(enabled_times)
|
||||
disabled_avg = sum(disabled_times) / len(disabled_times)
|
||||
|
||||
print(f"\n LLM Enabled avg: {enabled_avg:.1f}ms")
|
||||
print(f" LLM Disabled avg: {disabled_avg:.1f}ms")
|
||||
print(f" LLM Savings: {enabled_avg - disabled_avg:.1f}ms")
|
||||
|
||||
assert disabled_avg < enabled_avg, (
|
||||
f"Expected disabled ({disabled_avg:.1f}ms) to be faster than enabled ({enabled_avg:.1f}ms)"
|
||||
)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Graph retrieval config tests
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_graph_retrieval_defaults_to_true():
|
||||
"""Default value should be True (graph retrieval on)."""
|
||||
assert DEFAULT_ENABLE_GRAPH_RETRIEVAL is True
|
||||
|
||||
|
||||
def test_config_disables_graph_retrieval_when_false():
|
||||
"""Setting the env var to 'false' should disable graph retrieval."""
|
||||
os.environ[ENV_ENABLE_GRAPH_RETRIEVAL] = "false"
|
||||
os.environ.setdefault("HINDSIGHT_API_LLM_PROVIDER", "mock")
|
||||
config = HindsightConfig.from_env()
|
||||
assert config.enable_graph_retrieval is False
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Full RAG mode integration tests — temporal OFF + graph OFF (2-way retrieval)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_recall_with_both_temporal_and_graph_disabled(none_memory, request_context):
|
||||
"""
|
||||
With both temporal extraction and graph retrieval disabled, recall should
|
||||
still return results via semantic + BM25 only (2-way retrieval).
|
||||
"""
|
||||
bank_id = f"test_rag_mode_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await none_memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="Alice is a software engineer who specializes in distributed systems and Kubernetes.",
|
||||
context="team info",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
os.environ[ENV_ENABLE_GRAPH_RETRIEVAL] = "false"
|
||||
clear_config_cache()
|
||||
|
||||
result = await none_memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query="Who is Alice?",
|
||||
budget=Budget.LOW,
|
||||
include_chunks=True,
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
has_results = len(result.results) > 0 or (result.chunks is not None and len(result.chunks) > 0)
|
||||
assert has_results, "Should find results with 2-way retrieval (semantic + BM25 only)"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_llm_recall_rag_mode(memory, request_context):
|
||||
"""
|
||||
Full RAG mode with real LLM: temporal OFF + graph OFF.
|
||||
Recall should still find LLM-extracted facts via semantic + BM25.
|
||||
"""
|
||||
bank_id = f"test_llm_rag_{datetime.now(timezone.utc).timestamp()}"
|
||||
|
||||
await memory.retain_async(
|
||||
bank_id=bank_id,
|
||||
content="In March 2024, the team shipped the new authentication system. It replaced the legacy OAuth flow with OIDC.",
|
||||
context="engineering update",
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
os.environ[ENV_ENABLE_TEMPORAL_EXTRACTION] = "false"
|
||||
os.environ[ENV_ENABLE_GRAPH_RETRIEVAL] = "false"
|
||||
clear_config_cache()
|
||||
|
||||
result = await memory.recall_async(
|
||||
bank_id=bank_id,
|
||||
query="What happened with authentication?",
|
||||
budget=Budget.LOW,
|
||||
request_context=request_context,
|
||||
)
|
||||
|
||||
assert len(result.results) > 0, "Should find facts in RAG mode (2-way retrieval)"
|
||||
@@ -7,7 +7,7 @@ info:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
title: Hindsight HTTP API
|
||||
version: 0.5.0
|
||||
version: 0.5.2
|
||||
servers:
|
||||
- url: /
|
||||
paths:
|
||||
@@ -166,6 +166,14 @@ paths:
|
||||
nullable: true
|
||||
type: string
|
||||
style: form
|
||||
- explode: true
|
||||
in: query
|
||||
name: consolidation_state
|
||||
required: false
|
||||
schema:
|
||||
nullable: true
|
||||
type: string
|
||||
style: form
|
||||
- explode: true
|
||||
in: query
|
||||
name: limit
|
||||
@@ -464,6 +472,53 @@ paths:
|
||||
summary: Get statistics for memory bank
|
||||
tags:
|
||||
- Banks
|
||||
/v1/default/banks/{bank_id}/stats/memories-timeseries:
|
||||
get:
|
||||
description: "Memories ingested over a period, bucketed by time and broken down\
|
||||
\ by fact type."
|
||||
operationId: get_memories_timeseries
|
||||
parameters:
|
||||
- explode: false
|
||||
in: path
|
||||
name: bank_id
|
||||
required: true
|
||||
schema:
|
||||
title: Bank Id
|
||||
type: string
|
||||
style: simple
|
||||
- explode: true
|
||||
in: query
|
||||
name: period
|
||||
required: false
|
||||
schema:
|
||||
default: 7d
|
||||
title: Period
|
||||
type: string
|
||||
style: form
|
||||
- explode: false
|
||||
in: header
|
||||
name: authorization
|
||||
required: false
|
||||
schema:
|
||||
nullable: true
|
||||
type: string
|
||||
style: simple
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/MemoriesTimeseriesResponse'
|
||||
description: Successful Response
|
||||
"422":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/HTTPValidationError'
|
||||
description: Validation Error
|
||||
summary: Memory ingestion time-series
|
||||
tags:
|
||||
- Banks
|
||||
/v1/default/banks/{bank_id}/entities:
|
||||
get:
|
||||
description: "List all entities (people, organizations, etc.) known by the bank,\
|
||||
@@ -524,6 +579,66 @@ paths:
|
||||
summary: List entities
|
||||
tags:
|
||||
- Entities
|
||||
/v1/default/banks/{bank_id}/entities/graph:
|
||||
get:
|
||||
description: Return a graph of entities (nodes) and their co-occurrences (edges)
|
||||
for visualization.
|
||||
operationId: get_entity_graph
|
||||
parameters:
|
||||
- explode: false
|
||||
in: path
|
||||
name: bank_id
|
||||
required: true
|
||||
schema:
|
||||
title: Bank Id
|
||||
type: string
|
||||
style: simple
|
||||
- description: Maximum number of co-occurrence edges to return
|
||||
explode: true
|
||||
in: query
|
||||
name: limit
|
||||
required: false
|
||||
schema:
|
||||
default: 1000
|
||||
description: Maximum number of co-occurrence edges to return
|
||||
title: Limit
|
||||
type: integer
|
||||
style: form
|
||||
- description: Minimum cooccurrence_count to include an edge
|
||||
explode: true
|
||||
in: query
|
||||
name: min_count
|
||||
required: false
|
||||
schema:
|
||||
default: 1
|
||||
description: Minimum cooccurrence_count to include an edge
|
||||
title: Min Count
|
||||
type: integer
|
||||
style: form
|
||||
- explode: false
|
||||
in: header
|
||||
name: authorization
|
||||
required: false
|
||||
schema:
|
||||
nullable: true
|
||||
type: string
|
||||
style: simple
|
||||
responses:
|
||||
"200":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/EntityGraphResponse'
|
||||
description: Successful Response
|
||||
"422":
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/HTTPValidationError'
|
||||
description: Validation Error
|
||||
summary: Get entity co-occurrence graph
|
||||
tags:
|
||||
- Entities
|
||||
/v1/default/banks/{bank_id}/entities/{entity_id}:
|
||||
get:
|
||||
description: Get detailed information about an entity including observations
|
||||
@@ -1781,6 +1896,19 @@ paths:
|
||||
title: Operation Id
|
||||
type: string
|
||||
style: simple
|
||||
- description: Include the raw task payload (submission params) in the response.
|
||||
May be large.
|
||||
explode: true
|
||||
in: query
|
||||
name: include_payload
|
||||
required: false
|
||||
schema:
|
||||
default: false
|
||||
description: Include the raw task payload (submission params) in the response.
|
||||
May be large.
|
||||
title: Include Payload
|
||||
type: boolean
|
||||
style: form
|
||||
- explode: false
|
||||
in: header
|
||||
name: authorization
|
||||
@@ -3439,6 +3567,7 @@ components:
|
||||
description: Response model for bank statistics endpoint.
|
||||
example:
|
||||
bank_id: user123
|
||||
failed_consolidation: 0
|
||||
failed_operations: 0
|
||||
last_consolidated_at: 2024-01-15T10:30:00Z
|
||||
links_breakdown:
|
||||
@@ -3500,6 +3629,12 @@ components:
|
||||
failed_operations:
|
||||
title: Failed Operations
|
||||
type: integer
|
||||
operations_by_status:
|
||||
additionalProperties:
|
||||
type: integer
|
||||
description: "Async operations grouped by status (pending, in_progress,\
|
||||
\ completed, failed, cancelled)."
|
||||
title: Operations By Status
|
||||
last_consolidated_at:
|
||||
nullable: true
|
||||
type: string
|
||||
@@ -3508,6 +3643,12 @@ components:
|
||||
description: Number of memories not yet processed into observations
|
||||
title: Pending Consolidation
|
||||
type: integer
|
||||
failed_consolidation:
|
||||
default: 0
|
||||
description: Number of source memories (world/experience) whose consolidation
|
||||
permanently failed and can be retried via the consolidation recovery endpoint.
|
||||
title: Failed Consolidation
|
||||
type: integer
|
||||
total_observations:
|
||||
default: 0
|
||||
description: Total number of observations
|
||||
@@ -3576,6 +3717,66 @@ components:
|
||||
entities_allow_free_form:
|
||||
nullable: true
|
||||
type: boolean
|
||||
retain_default_strategy:
|
||||
nullable: true
|
||||
type: string
|
||||
retain_strategies:
|
||||
additionalProperties: {}
|
||||
nullable: true
|
||||
retain_chunk_batch_size:
|
||||
nullable: true
|
||||
type: integer
|
||||
mcp_enabled_tools:
|
||||
items:
|
||||
type: string
|
||||
nullable: true
|
||||
type: array
|
||||
consolidation_llm_batch_size:
|
||||
nullable: true
|
||||
type: integer
|
||||
consolidation_source_facts_max_tokens:
|
||||
nullable: true
|
||||
type: integer
|
||||
consolidation_source_facts_max_tokens_per_observation:
|
||||
nullable: true
|
||||
type: integer
|
||||
max_observations_per_scope:
|
||||
nullable: true
|
||||
type: integer
|
||||
reflect_source_facts_max_tokens:
|
||||
nullable: true
|
||||
type: integer
|
||||
llm_gemini_safety_settings:
|
||||
items: {}
|
||||
nullable: true
|
||||
type: array
|
||||
recall_budget_function:
|
||||
nullable: true
|
||||
type: string
|
||||
recall_budget_fixed_low:
|
||||
nullable: true
|
||||
type: integer
|
||||
recall_budget_fixed_mid:
|
||||
nullable: true
|
||||
type: integer
|
||||
recall_budget_fixed_high:
|
||||
nullable: true
|
||||
type: integer
|
||||
recall_budget_adaptive_low:
|
||||
nullable: true
|
||||
type: number
|
||||
recall_budget_adaptive_mid:
|
||||
nullable: true
|
||||
type: number
|
||||
recall_budget_adaptive_high:
|
||||
nullable: true
|
||||
type: number
|
||||
recall_budget_min:
|
||||
nullable: true
|
||||
type: integer
|
||||
recall_budget_max:
|
||||
nullable: true
|
||||
type: integer
|
||||
title: BankTemplateConfig
|
||||
BankTemplateDirective:
|
||||
description: |-
|
||||
@@ -4381,6 +4582,58 @@ components:
|
||||
- mention_count
|
||||
- observations
|
||||
title: EntityDetailResponse
|
||||
EntityGraphResponse:
|
||||
description: Response model for entity co-occurrence graph endpoint.
|
||||
example:
|
||||
edges:
|
||||
- data:
|
||||
color: '#ffd700'
|
||||
id: uuid-1-uuid-2
|
||||
lastCooccurred: 2024-02-01T14:00:00Z
|
||||
lineStyle: solid
|
||||
linkType: cooccurrence
|
||||
source: uuid-1
|
||||
target: uuid-2
|
||||
weight: 5
|
||||
limit: 1000
|
||||
nodes:
|
||||
- data:
|
||||
color: '#42a5f5'
|
||||
id: uuid-1
|
||||
label: Alice
|
||||
mentionCount: 12
|
||||
- data:
|
||||
color: '#42a5f5'
|
||||
id: uuid-2
|
||||
label: Google
|
||||
mentionCount: 8
|
||||
total_edges: 1
|
||||
total_entities: 2
|
||||
properties:
|
||||
nodes:
|
||||
items:
|
||||
additionalProperties: {}
|
||||
type: array
|
||||
edges:
|
||||
items:
|
||||
additionalProperties: {}
|
||||
type: array
|
||||
total_entities:
|
||||
title: Total Entities
|
||||
type: integer
|
||||
total_edges:
|
||||
title: Total Edges
|
||||
type: integer
|
||||
limit:
|
||||
title: Limit
|
||||
type: integer
|
||||
required:
|
||||
- edges
|
||||
- limit
|
||||
- nodes
|
||||
- total_edges
|
||||
- total_entities
|
||||
title: EntityGraphResponse
|
||||
EntityIncludeOptions:
|
||||
description: Options for including entity observations in recall results.
|
||||
properties:
|
||||
@@ -4736,6 +4989,44 @@ components:
|
||||
- offset
|
||||
- total
|
||||
title: ListTagsResponse
|
||||
MemoriesTimeseriesResponse:
|
||||
description: Time-series of memory ingestion bucketed by time and fact type.
|
||||
example:
|
||||
period: period
|
||||
trunc: trunc
|
||||
bank_id: bank_id
|
||||
buckets:
|
||||
- world: 0
|
||||
observation: 1
|
||||
time: time
|
||||
experience: 6
|
||||
- world: 0
|
||||
observation: 1
|
||||
time: time
|
||||
experience: 6
|
||||
properties:
|
||||
bank_id:
|
||||
title: Bank Id
|
||||
type: string
|
||||
period:
|
||||
description: "One of: 1h, 12h, 1d, 7d, 30d, 90d."
|
||||
title: Period
|
||||
type: string
|
||||
trunc:
|
||||
description: "Bucket granularity: minute, hour, day."
|
||||
title: Trunc
|
||||
type: string
|
||||
buckets:
|
||||
description: "Per-bucket counts, always returned fully padded for the requested\
|
||||
\ period."
|
||||
items:
|
||||
$ref: '#/components/schemas/MemoryTimeseriesBucket'
|
||||
type: array
|
||||
required:
|
||||
- bank_id
|
||||
- period
|
||||
- trunc
|
||||
title: MemoriesTimeseriesResponse
|
||||
MemoryItem:
|
||||
description: Single memory item for retain.
|
||||
example:
|
||||
@@ -4793,6 +5084,36 @@ components:
|
||||
required:
|
||||
- content
|
||||
title: MemoryItem
|
||||
MemoryTimeseriesBucket:
|
||||
description: One bucket in the memory ingestion time-series.
|
||||
example:
|
||||
world: 0
|
||||
observation: 1
|
||||
time: time
|
||||
experience: 6
|
||||
properties:
|
||||
time:
|
||||
description: Bucket start timestamp in ISO-8601 (UTC).
|
||||
title: Time
|
||||
type: string
|
||||
world:
|
||||
default: 0
|
||||
description: World-fact memories ingested in this bucket.
|
||||
title: World
|
||||
type: integer
|
||||
experience:
|
||||
default: 0
|
||||
description: Experience memories ingested in this bucket.
|
||||
title: Experience
|
||||
type: integer
|
||||
observation:
|
||||
default: 0
|
||||
description: Observations recorded in this bucket.
|
||||
title: Observation
|
||||
type: integer
|
||||
required:
|
||||
- time
|
||||
title: MemoryTimeseriesBucket
|
||||
MentalModelListResponse:
|
||||
description: Response model for listing mental models.
|
||||
example:
|
||||
@@ -4807,6 +5128,7 @@ components:
|
||||
id: id
|
||||
trigger:
|
||||
refresh_after_consolidation: false
|
||||
recall_chunks_max_tokens: 1
|
||||
tag_groups:
|
||||
- match: any_strict
|
||||
tags:
|
||||
@@ -4822,9 +5144,12 @@ components:
|
||||
exclude_mental_model_ids:
|
||||
- exclude_mental_model_ids
|
||||
- exclude_mental_model_ids
|
||||
include_chunks: true
|
||||
tags_match: any
|
||||
exclude_mental_models: false
|
||||
recall_max_tokens: 6
|
||||
last_refreshed_at: last_refreshed_at
|
||||
is_stale: true
|
||||
content: content
|
||||
tags:
|
||||
- tags
|
||||
@@ -4839,6 +5164,7 @@ components:
|
||||
id: id
|
||||
trigger:
|
||||
refresh_after_consolidation: false
|
||||
recall_chunks_max_tokens: 1
|
||||
tag_groups:
|
||||
- match: any_strict
|
||||
tags:
|
||||
@@ -4854,9 +5180,12 @@ components:
|
||||
exclude_mental_model_ids:
|
||||
- exclude_mental_model_ids
|
||||
- exclude_mental_model_ids
|
||||
include_chunks: true
|
||||
tags_match: any
|
||||
exclude_mental_models: false
|
||||
recall_max_tokens: 6
|
||||
last_refreshed_at: last_refreshed_at
|
||||
is_stale: true
|
||||
content: content
|
||||
tags:
|
||||
- tags
|
||||
@@ -4882,6 +5211,7 @@ components:
|
||||
id: id
|
||||
trigger:
|
||||
refresh_after_consolidation: false
|
||||
recall_chunks_max_tokens: 1
|
||||
tag_groups:
|
||||
- match: any_strict
|
||||
tags:
|
||||
@@ -4897,9 +5227,12 @@ components:
|
||||
exclude_mental_model_ids:
|
||||
- exclude_mental_model_ids
|
||||
- exclude_mental_model_ids
|
||||
include_chunks: true
|
||||
tags_match: any
|
||||
exclude_mental_models: false
|
||||
recall_max_tokens: 6
|
||||
last_refreshed_at: last_refreshed_at
|
||||
is_stale: true
|
||||
content: content
|
||||
tags:
|
||||
- tags
|
||||
@@ -4939,6 +5272,9 @@ components:
|
||||
reflect_response:
|
||||
additionalProperties: {}
|
||||
nullable: true
|
||||
is_stale:
|
||||
nullable: true
|
||||
type: boolean
|
||||
required:
|
||||
- bank_id
|
||||
- id
|
||||
@@ -4986,11 +5322,21 @@ components:
|
||||
$ref: '#/components/schemas/MentalModelTrigger_Input_tag_groups_inner'
|
||||
nullable: true
|
||||
type: array
|
||||
include_chunks:
|
||||
nullable: true
|
||||
type: boolean
|
||||
recall_max_tokens:
|
||||
nullable: true
|
||||
type: integer
|
||||
recall_chunks_max_tokens:
|
||||
nullable: true
|
||||
type: integer
|
||||
title: MentalModelTrigger
|
||||
MentalModelTrigger-Output:
|
||||
description: Trigger settings for a mental model.
|
||||
example:
|
||||
refresh_after_consolidation: false
|
||||
recall_chunks_max_tokens: 1
|
||||
tag_groups:
|
||||
- match: any_strict
|
||||
tags:
|
||||
@@ -5006,8 +5352,10 @@ components:
|
||||
exclude_mental_model_ids:
|
||||
- exclude_mental_model_ids
|
||||
- exclude_mental_model_ids
|
||||
include_chunks: true
|
||||
tags_match: any
|
||||
exclude_mental_models: false
|
||||
recall_max_tokens: 6
|
||||
properties:
|
||||
refresh_after_consolidation:
|
||||
default: false
|
||||
@@ -5048,6 +5396,15 @@ components:
|
||||
$ref: '#/components/schemas/MentalModelTrigger_Output_tag_groups_inner'
|
||||
nullable: true
|
||||
type: array
|
||||
include_chunks:
|
||||
nullable: true
|
||||
type: boolean
|
||||
recall_max_tokens:
|
||||
nullable: true
|
||||
type: integer
|
||||
recall_chunks_max_tokens:
|
||||
nullable: true
|
||||
type: integer
|
||||
title: MentalModelTrigger
|
||||
OperationResponse:
|
||||
description: Response model for a single async operation.
|
||||
@@ -5131,6 +5488,9 @@ components:
|
||||
$ref: '#/components/schemas/ChildOperationStatus'
|
||||
nullable: true
|
||||
type: array
|
||||
task_payload:
|
||||
additionalProperties: {}
|
||||
nullable: true
|
||||
required:
|
||||
- operation_id
|
||||
- status
|
||||
|
||||
@@ -3,7 +3,7 @@ Hindsight HTTP API
|
||||
|
||||
HTTP API for Hindsight
|
||||
|
||||
API version: 0.5.0
|
||||
API version: 0.5.2
|
||||
*/
|
||||
|
||||
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
|
||||
@@ -31,6 +31,25 @@ type BankTemplateConfig struct {
|
||||
DispositionEmpathy NullableInt32 `json:"disposition_empathy,omitempty"`
|
||||
EntityLabels []map[string]interface{} `json:"entity_labels,omitempty"`
|
||||
EntitiesAllowFreeForm NullableBool `json:"entities_allow_free_form,omitempty"`
|
||||
RetainDefaultStrategy NullableString `json:"retain_default_strategy,omitempty"`
|
||||
RetainStrategies map[string]interface{} `json:"retain_strategies,omitempty"`
|
||||
RetainChunkBatchSize NullableInt32 `json:"retain_chunk_batch_size,omitempty"`
|
||||
McpEnabledTools []string `json:"mcp_enabled_tools,omitempty"`
|
||||
ConsolidationLlmBatchSize NullableInt32 `json:"consolidation_llm_batch_size,omitempty"`
|
||||
ConsolidationSourceFactsMaxTokens NullableInt32 `json:"consolidation_source_facts_max_tokens,omitempty"`
|
||||
ConsolidationSourceFactsMaxTokensPerObservation NullableInt32 `json:"consolidation_source_facts_max_tokens_per_observation,omitempty"`
|
||||
MaxObservationsPerScope NullableInt32 `json:"max_observations_per_scope,omitempty"`
|
||||
ReflectSourceFactsMaxTokens NullableInt32 `json:"reflect_source_facts_max_tokens,omitempty"`
|
||||
LlmGeminiSafetySettings []interface{} `json:"llm_gemini_safety_settings,omitempty"`
|
||||
RecallBudgetFunction NullableString `json:"recall_budget_function,omitempty"`
|
||||
RecallBudgetFixedLow NullableInt32 `json:"recall_budget_fixed_low,omitempty"`
|
||||
RecallBudgetFixedMid NullableInt32 `json:"recall_budget_fixed_mid,omitempty"`
|
||||
RecallBudgetFixedHigh NullableInt32 `json:"recall_budget_fixed_high,omitempty"`
|
||||
RecallBudgetAdaptiveLow NullableFloat32 `json:"recall_budget_adaptive_low,omitempty"`
|
||||
RecallBudgetAdaptiveMid NullableFloat32 `json:"recall_budget_adaptive_mid,omitempty"`
|
||||
RecallBudgetAdaptiveHigh NullableFloat32 `json:"recall_budget_adaptive_high,omitempty"`
|
||||
RecallBudgetMin NullableInt32 `json:"recall_budget_min,omitempty"`
|
||||
RecallBudgetMax NullableInt32 `json:"recall_budget_max,omitempty"`
|
||||
}
|
||||
|
||||
// NewBankTemplateConfig instantiates a new BankTemplateConfig object
|
||||
@@ -545,6 +564,777 @@ func (o *BankTemplateConfig) UnsetEntitiesAllowFreeForm() {
|
||||
o.EntitiesAllowFreeForm.Unset()
|
||||
}
|
||||
|
||||
// GetRetainDefaultStrategy returns the RetainDefaultStrategy field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRetainDefaultStrategy() string {
|
||||
if o == nil || IsNil(o.RetainDefaultStrategy.Get()) {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
return *o.RetainDefaultStrategy.Get()
|
||||
}
|
||||
|
||||
// GetRetainDefaultStrategyOk returns a tuple with the RetainDefaultStrategy field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRetainDefaultStrategyOk() (*string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RetainDefaultStrategy.Get(), o.RetainDefaultStrategy.IsSet()
|
||||
}
|
||||
|
||||
// HasRetainDefaultStrategy returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRetainDefaultStrategy() bool {
|
||||
if o != nil && o.RetainDefaultStrategy.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRetainDefaultStrategy gets a reference to the given NullableString and assigns it to the RetainDefaultStrategy field.
|
||||
func (o *BankTemplateConfig) SetRetainDefaultStrategy(v string) {
|
||||
o.RetainDefaultStrategy.Set(&v)
|
||||
}
|
||||
// SetRetainDefaultStrategyNil sets the value for RetainDefaultStrategy to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRetainDefaultStrategyNil() {
|
||||
o.RetainDefaultStrategy.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRetainDefaultStrategy ensures that no value is present for RetainDefaultStrategy, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRetainDefaultStrategy() {
|
||||
o.RetainDefaultStrategy.Unset()
|
||||
}
|
||||
|
||||
// GetRetainStrategies returns the RetainStrategies field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRetainStrategies() map[string]interface{} {
|
||||
if o == nil {
|
||||
var ret map[string]interface{}
|
||||
return ret
|
||||
}
|
||||
return o.RetainStrategies
|
||||
}
|
||||
|
||||
// GetRetainStrategiesOk returns a tuple with the RetainStrategies field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRetainStrategiesOk() (map[string]interface{}, bool) {
|
||||
if o == nil || IsNil(o.RetainStrategies) {
|
||||
return map[string]interface{}{}, false
|
||||
}
|
||||
return o.RetainStrategies, true
|
||||
}
|
||||
|
||||
// HasRetainStrategies returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRetainStrategies() bool {
|
||||
if o != nil && !IsNil(o.RetainStrategies) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRetainStrategies gets a reference to the given map[string]interface{} and assigns it to the RetainStrategies field.
|
||||
func (o *BankTemplateConfig) SetRetainStrategies(v map[string]interface{}) {
|
||||
o.RetainStrategies = v
|
||||
}
|
||||
|
||||
// GetRetainChunkBatchSize returns the RetainChunkBatchSize field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRetainChunkBatchSize() int32 {
|
||||
if o == nil || IsNil(o.RetainChunkBatchSize.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.RetainChunkBatchSize.Get()
|
||||
}
|
||||
|
||||
// GetRetainChunkBatchSizeOk returns a tuple with the RetainChunkBatchSize field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRetainChunkBatchSizeOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RetainChunkBatchSize.Get(), o.RetainChunkBatchSize.IsSet()
|
||||
}
|
||||
|
||||
// HasRetainChunkBatchSize returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRetainChunkBatchSize() bool {
|
||||
if o != nil && o.RetainChunkBatchSize.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRetainChunkBatchSize gets a reference to the given NullableInt32 and assigns it to the RetainChunkBatchSize field.
|
||||
func (o *BankTemplateConfig) SetRetainChunkBatchSize(v int32) {
|
||||
o.RetainChunkBatchSize.Set(&v)
|
||||
}
|
||||
// SetRetainChunkBatchSizeNil sets the value for RetainChunkBatchSize to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRetainChunkBatchSizeNil() {
|
||||
o.RetainChunkBatchSize.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRetainChunkBatchSize ensures that no value is present for RetainChunkBatchSize, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRetainChunkBatchSize() {
|
||||
o.RetainChunkBatchSize.Unset()
|
||||
}
|
||||
|
||||
// GetMcpEnabledTools returns the McpEnabledTools field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetMcpEnabledTools() []string {
|
||||
if o == nil {
|
||||
var ret []string
|
||||
return ret
|
||||
}
|
||||
return o.McpEnabledTools
|
||||
}
|
||||
|
||||
// GetMcpEnabledToolsOk returns a tuple with the McpEnabledTools field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetMcpEnabledToolsOk() ([]string, bool) {
|
||||
if o == nil || IsNil(o.McpEnabledTools) {
|
||||
return nil, false
|
||||
}
|
||||
return o.McpEnabledTools, true
|
||||
}
|
||||
|
||||
// HasMcpEnabledTools returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasMcpEnabledTools() bool {
|
||||
if o != nil && !IsNil(o.McpEnabledTools) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetMcpEnabledTools gets a reference to the given []string and assigns it to the McpEnabledTools field.
|
||||
func (o *BankTemplateConfig) SetMcpEnabledTools(v []string) {
|
||||
o.McpEnabledTools = v
|
||||
}
|
||||
|
||||
// GetConsolidationLlmBatchSize returns the ConsolidationLlmBatchSize field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetConsolidationLlmBatchSize() int32 {
|
||||
if o == nil || IsNil(o.ConsolidationLlmBatchSize.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.ConsolidationLlmBatchSize.Get()
|
||||
}
|
||||
|
||||
// GetConsolidationLlmBatchSizeOk returns a tuple with the ConsolidationLlmBatchSize field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetConsolidationLlmBatchSizeOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.ConsolidationLlmBatchSize.Get(), o.ConsolidationLlmBatchSize.IsSet()
|
||||
}
|
||||
|
||||
// HasConsolidationLlmBatchSize returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasConsolidationLlmBatchSize() bool {
|
||||
if o != nil && o.ConsolidationLlmBatchSize.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetConsolidationLlmBatchSize gets a reference to the given NullableInt32 and assigns it to the ConsolidationLlmBatchSize field.
|
||||
func (o *BankTemplateConfig) SetConsolidationLlmBatchSize(v int32) {
|
||||
o.ConsolidationLlmBatchSize.Set(&v)
|
||||
}
|
||||
// SetConsolidationLlmBatchSizeNil sets the value for ConsolidationLlmBatchSize to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetConsolidationLlmBatchSizeNil() {
|
||||
o.ConsolidationLlmBatchSize.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetConsolidationLlmBatchSize ensures that no value is present for ConsolidationLlmBatchSize, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetConsolidationLlmBatchSize() {
|
||||
o.ConsolidationLlmBatchSize.Unset()
|
||||
}
|
||||
|
||||
// GetConsolidationSourceFactsMaxTokens returns the ConsolidationSourceFactsMaxTokens field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetConsolidationSourceFactsMaxTokens() int32 {
|
||||
if o == nil || IsNil(o.ConsolidationSourceFactsMaxTokens.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.ConsolidationSourceFactsMaxTokens.Get()
|
||||
}
|
||||
|
||||
// GetConsolidationSourceFactsMaxTokensOk returns a tuple with the ConsolidationSourceFactsMaxTokens field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetConsolidationSourceFactsMaxTokensOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.ConsolidationSourceFactsMaxTokens.Get(), o.ConsolidationSourceFactsMaxTokens.IsSet()
|
||||
}
|
||||
|
||||
// HasConsolidationSourceFactsMaxTokens returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasConsolidationSourceFactsMaxTokens() bool {
|
||||
if o != nil && o.ConsolidationSourceFactsMaxTokens.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetConsolidationSourceFactsMaxTokens gets a reference to the given NullableInt32 and assigns it to the ConsolidationSourceFactsMaxTokens field.
|
||||
func (o *BankTemplateConfig) SetConsolidationSourceFactsMaxTokens(v int32) {
|
||||
o.ConsolidationSourceFactsMaxTokens.Set(&v)
|
||||
}
|
||||
// SetConsolidationSourceFactsMaxTokensNil sets the value for ConsolidationSourceFactsMaxTokens to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetConsolidationSourceFactsMaxTokensNil() {
|
||||
o.ConsolidationSourceFactsMaxTokens.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetConsolidationSourceFactsMaxTokens ensures that no value is present for ConsolidationSourceFactsMaxTokens, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetConsolidationSourceFactsMaxTokens() {
|
||||
o.ConsolidationSourceFactsMaxTokens.Unset()
|
||||
}
|
||||
|
||||
// GetConsolidationSourceFactsMaxTokensPerObservation returns the ConsolidationSourceFactsMaxTokensPerObservation field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetConsolidationSourceFactsMaxTokensPerObservation() int32 {
|
||||
if o == nil || IsNil(o.ConsolidationSourceFactsMaxTokensPerObservation.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.ConsolidationSourceFactsMaxTokensPerObservation.Get()
|
||||
}
|
||||
|
||||
// GetConsolidationSourceFactsMaxTokensPerObservationOk returns a tuple with the ConsolidationSourceFactsMaxTokensPerObservation field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetConsolidationSourceFactsMaxTokensPerObservationOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.ConsolidationSourceFactsMaxTokensPerObservation.Get(), o.ConsolidationSourceFactsMaxTokensPerObservation.IsSet()
|
||||
}
|
||||
|
||||
// HasConsolidationSourceFactsMaxTokensPerObservation returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasConsolidationSourceFactsMaxTokensPerObservation() bool {
|
||||
if o != nil && o.ConsolidationSourceFactsMaxTokensPerObservation.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetConsolidationSourceFactsMaxTokensPerObservation gets a reference to the given NullableInt32 and assigns it to the ConsolidationSourceFactsMaxTokensPerObservation field.
|
||||
func (o *BankTemplateConfig) SetConsolidationSourceFactsMaxTokensPerObservation(v int32) {
|
||||
o.ConsolidationSourceFactsMaxTokensPerObservation.Set(&v)
|
||||
}
|
||||
// SetConsolidationSourceFactsMaxTokensPerObservationNil sets the value for ConsolidationSourceFactsMaxTokensPerObservation to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetConsolidationSourceFactsMaxTokensPerObservationNil() {
|
||||
o.ConsolidationSourceFactsMaxTokensPerObservation.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetConsolidationSourceFactsMaxTokensPerObservation ensures that no value is present for ConsolidationSourceFactsMaxTokensPerObservation, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetConsolidationSourceFactsMaxTokensPerObservation() {
|
||||
o.ConsolidationSourceFactsMaxTokensPerObservation.Unset()
|
||||
}
|
||||
|
||||
// GetMaxObservationsPerScope returns the MaxObservationsPerScope field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetMaxObservationsPerScope() int32 {
|
||||
if o == nil || IsNil(o.MaxObservationsPerScope.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.MaxObservationsPerScope.Get()
|
||||
}
|
||||
|
||||
// GetMaxObservationsPerScopeOk returns a tuple with the MaxObservationsPerScope field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetMaxObservationsPerScopeOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.MaxObservationsPerScope.Get(), o.MaxObservationsPerScope.IsSet()
|
||||
}
|
||||
|
||||
// HasMaxObservationsPerScope returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasMaxObservationsPerScope() bool {
|
||||
if o != nil && o.MaxObservationsPerScope.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetMaxObservationsPerScope gets a reference to the given NullableInt32 and assigns it to the MaxObservationsPerScope field.
|
||||
func (o *BankTemplateConfig) SetMaxObservationsPerScope(v int32) {
|
||||
o.MaxObservationsPerScope.Set(&v)
|
||||
}
|
||||
// SetMaxObservationsPerScopeNil sets the value for MaxObservationsPerScope to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetMaxObservationsPerScopeNil() {
|
||||
o.MaxObservationsPerScope.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetMaxObservationsPerScope ensures that no value is present for MaxObservationsPerScope, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetMaxObservationsPerScope() {
|
||||
o.MaxObservationsPerScope.Unset()
|
||||
}
|
||||
|
||||
// GetReflectSourceFactsMaxTokens returns the ReflectSourceFactsMaxTokens field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetReflectSourceFactsMaxTokens() int32 {
|
||||
if o == nil || IsNil(o.ReflectSourceFactsMaxTokens.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.ReflectSourceFactsMaxTokens.Get()
|
||||
}
|
||||
|
||||
// GetReflectSourceFactsMaxTokensOk returns a tuple with the ReflectSourceFactsMaxTokens field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetReflectSourceFactsMaxTokensOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.ReflectSourceFactsMaxTokens.Get(), o.ReflectSourceFactsMaxTokens.IsSet()
|
||||
}
|
||||
|
||||
// HasReflectSourceFactsMaxTokens returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasReflectSourceFactsMaxTokens() bool {
|
||||
if o != nil && o.ReflectSourceFactsMaxTokens.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetReflectSourceFactsMaxTokens gets a reference to the given NullableInt32 and assigns it to the ReflectSourceFactsMaxTokens field.
|
||||
func (o *BankTemplateConfig) SetReflectSourceFactsMaxTokens(v int32) {
|
||||
o.ReflectSourceFactsMaxTokens.Set(&v)
|
||||
}
|
||||
// SetReflectSourceFactsMaxTokensNil sets the value for ReflectSourceFactsMaxTokens to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetReflectSourceFactsMaxTokensNil() {
|
||||
o.ReflectSourceFactsMaxTokens.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetReflectSourceFactsMaxTokens ensures that no value is present for ReflectSourceFactsMaxTokens, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetReflectSourceFactsMaxTokens() {
|
||||
o.ReflectSourceFactsMaxTokens.Unset()
|
||||
}
|
||||
|
||||
// GetLlmGeminiSafetySettings returns the LlmGeminiSafetySettings field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetLlmGeminiSafetySettings() []interface{} {
|
||||
if o == nil {
|
||||
var ret []interface{}
|
||||
return ret
|
||||
}
|
||||
return o.LlmGeminiSafetySettings
|
||||
}
|
||||
|
||||
// GetLlmGeminiSafetySettingsOk returns a tuple with the LlmGeminiSafetySettings field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetLlmGeminiSafetySettingsOk() ([]interface{}, bool) {
|
||||
if o == nil || IsNil(o.LlmGeminiSafetySettings) {
|
||||
return nil, false
|
||||
}
|
||||
return o.LlmGeminiSafetySettings, true
|
||||
}
|
||||
|
||||
// HasLlmGeminiSafetySettings returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasLlmGeminiSafetySettings() bool {
|
||||
if o != nil && !IsNil(o.LlmGeminiSafetySettings) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetLlmGeminiSafetySettings gets a reference to the given []interface{} and assigns it to the LlmGeminiSafetySettings field.
|
||||
func (o *BankTemplateConfig) SetLlmGeminiSafetySettings(v []interface{}) {
|
||||
o.LlmGeminiSafetySettings = v
|
||||
}
|
||||
|
||||
// GetRecallBudgetFunction returns the RecallBudgetFunction field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFunction() string {
|
||||
if o == nil || IsNil(o.RecallBudgetFunction.Get()) {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetFunction.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetFunctionOk returns a tuple with the RecallBudgetFunction field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFunctionOk() (*string, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetFunction.Get(), o.RecallBudgetFunction.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetFunction returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetFunction() bool {
|
||||
if o != nil && o.RecallBudgetFunction.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetFunction gets a reference to the given NullableString and assigns it to the RecallBudgetFunction field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFunction(v string) {
|
||||
o.RecallBudgetFunction.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetFunctionNil sets the value for RecallBudgetFunction to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFunctionNil() {
|
||||
o.RecallBudgetFunction.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetFunction ensures that no value is present for RecallBudgetFunction, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetFunction() {
|
||||
o.RecallBudgetFunction.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetFixedLow returns the RecallBudgetFixedLow field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFixedLow() int32 {
|
||||
if o == nil || IsNil(o.RecallBudgetFixedLow.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetFixedLow.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetFixedLowOk returns a tuple with the RecallBudgetFixedLow field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFixedLowOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetFixedLow.Get(), o.RecallBudgetFixedLow.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetFixedLow returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetFixedLow() bool {
|
||||
if o != nil && o.RecallBudgetFixedLow.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetFixedLow gets a reference to the given NullableInt32 and assigns it to the RecallBudgetFixedLow field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFixedLow(v int32) {
|
||||
o.RecallBudgetFixedLow.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetFixedLowNil sets the value for RecallBudgetFixedLow to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFixedLowNil() {
|
||||
o.RecallBudgetFixedLow.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetFixedLow ensures that no value is present for RecallBudgetFixedLow, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetFixedLow() {
|
||||
o.RecallBudgetFixedLow.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetFixedMid returns the RecallBudgetFixedMid field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFixedMid() int32 {
|
||||
if o == nil || IsNil(o.RecallBudgetFixedMid.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetFixedMid.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetFixedMidOk returns a tuple with the RecallBudgetFixedMid field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFixedMidOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetFixedMid.Get(), o.RecallBudgetFixedMid.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetFixedMid returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetFixedMid() bool {
|
||||
if o != nil && o.RecallBudgetFixedMid.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetFixedMid gets a reference to the given NullableInt32 and assigns it to the RecallBudgetFixedMid field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFixedMid(v int32) {
|
||||
o.RecallBudgetFixedMid.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetFixedMidNil sets the value for RecallBudgetFixedMid to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFixedMidNil() {
|
||||
o.RecallBudgetFixedMid.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetFixedMid ensures that no value is present for RecallBudgetFixedMid, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetFixedMid() {
|
||||
o.RecallBudgetFixedMid.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetFixedHigh returns the RecallBudgetFixedHigh field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFixedHigh() int32 {
|
||||
if o == nil || IsNil(o.RecallBudgetFixedHigh.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetFixedHigh.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetFixedHighOk returns a tuple with the RecallBudgetFixedHigh field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetFixedHighOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetFixedHigh.Get(), o.RecallBudgetFixedHigh.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetFixedHigh returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetFixedHigh() bool {
|
||||
if o != nil && o.RecallBudgetFixedHigh.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetFixedHigh gets a reference to the given NullableInt32 and assigns it to the RecallBudgetFixedHigh field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFixedHigh(v int32) {
|
||||
o.RecallBudgetFixedHigh.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetFixedHighNil sets the value for RecallBudgetFixedHigh to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetFixedHighNil() {
|
||||
o.RecallBudgetFixedHigh.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetFixedHigh ensures that no value is present for RecallBudgetFixedHigh, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetFixedHigh() {
|
||||
o.RecallBudgetFixedHigh.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetAdaptiveLow returns the RecallBudgetAdaptiveLow field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetAdaptiveLow() float32 {
|
||||
if o == nil || IsNil(o.RecallBudgetAdaptiveLow.Get()) {
|
||||
var ret float32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetAdaptiveLow.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetAdaptiveLowOk returns a tuple with the RecallBudgetAdaptiveLow field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetAdaptiveLowOk() (*float32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetAdaptiveLow.Get(), o.RecallBudgetAdaptiveLow.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetAdaptiveLow returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetAdaptiveLow() bool {
|
||||
if o != nil && o.RecallBudgetAdaptiveLow.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetAdaptiveLow gets a reference to the given NullableFloat32 and assigns it to the RecallBudgetAdaptiveLow field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetAdaptiveLow(v float32) {
|
||||
o.RecallBudgetAdaptiveLow.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetAdaptiveLowNil sets the value for RecallBudgetAdaptiveLow to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetAdaptiveLowNil() {
|
||||
o.RecallBudgetAdaptiveLow.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetAdaptiveLow ensures that no value is present for RecallBudgetAdaptiveLow, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetAdaptiveLow() {
|
||||
o.RecallBudgetAdaptiveLow.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetAdaptiveMid returns the RecallBudgetAdaptiveMid field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetAdaptiveMid() float32 {
|
||||
if o == nil || IsNil(o.RecallBudgetAdaptiveMid.Get()) {
|
||||
var ret float32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetAdaptiveMid.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetAdaptiveMidOk returns a tuple with the RecallBudgetAdaptiveMid field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetAdaptiveMidOk() (*float32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetAdaptiveMid.Get(), o.RecallBudgetAdaptiveMid.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetAdaptiveMid returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetAdaptiveMid() bool {
|
||||
if o != nil && o.RecallBudgetAdaptiveMid.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetAdaptiveMid gets a reference to the given NullableFloat32 and assigns it to the RecallBudgetAdaptiveMid field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetAdaptiveMid(v float32) {
|
||||
o.RecallBudgetAdaptiveMid.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetAdaptiveMidNil sets the value for RecallBudgetAdaptiveMid to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetAdaptiveMidNil() {
|
||||
o.RecallBudgetAdaptiveMid.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetAdaptiveMid ensures that no value is present for RecallBudgetAdaptiveMid, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetAdaptiveMid() {
|
||||
o.RecallBudgetAdaptiveMid.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetAdaptiveHigh returns the RecallBudgetAdaptiveHigh field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetAdaptiveHigh() float32 {
|
||||
if o == nil || IsNil(o.RecallBudgetAdaptiveHigh.Get()) {
|
||||
var ret float32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetAdaptiveHigh.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetAdaptiveHighOk returns a tuple with the RecallBudgetAdaptiveHigh field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetAdaptiveHighOk() (*float32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetAdaptiveHigh.Get(), o.RecallBudgetAdaptiveHigh.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetAdaptiveHigh returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetAdaptiveHigh() bool {
|
||||
if o != nil && o.RecallBudgetAdaptiveHigh.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetAdaptiveHigh gets a reference to the given NullableFloat32 and assigns it to the RecallBudgetAdaptiveHigh field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetAdaptiveHigh(v float32) {
|
||||
o.RecallBudgetAdaptiveHigh.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetAdaptiveHighNil sets the value for RecallBudgetAdaptiveHigh to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetAdaptiveHighNil() {
|
||||
o.RecallBudgetAdaptiveHigh.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetAdaptiveHigh ensures that no value is present for RecallBudgetAdaptiveHigh, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetAdaptiveHigh() {
|
||||
o.RecallBudgetAdaptiveHigh.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetMin returns the RecallBudgetMin field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetMin() int32 {
|
||||
if o == nil || IsNil(o.RecallBudgetMin.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetMin.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetMinOk returns a tuple with the RecallBudgetMin field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetMinOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetMin.Get(), o.RecallBudgetMin.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetMin returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetMin() bool {
|
||||
if o != nil && o.RecallBudgetMin.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetMin gets a reference to the given NullableInt32 and assigns it to the RecallBudgetMin field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetMin(v int32) {
|
||||
o.RecallBudgetMin.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetMinNil sets the value for RecallBudgetMin to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetMinNil() {
|
||||
o.RecallBudgetMin.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetMin ensures that no value is present for RecallBudgetMin, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetMin() {
|
||||
o.RecallBudgetMin.Unset()
|
||||
}
|
||||
|
||||
// GetRecallBudgetMax returns the RecallBudgetMax field value if set, zero value otherwise (both if not set or set to explicit null).
|
||||
func (o *BankTemplateConfig) GetRecallBudgetMax() int32 {
|
||||
if o == nil || IsNil(o.RecallBudgetMax.Get()) {
|
||||
var ret int32
|
||||
return ret
|
||||
}
|
||||
return *o.RecallBudgetMax.Get()
|
||||
}
|
||||
|
||||
// GetRecallBudgetMaxOk returns a tuple with the RecallBudgetMax field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
// NOTE: If the value is an explicit nil, `nil, true` will be returned
|
||||
func (o *BankTemplateConfig) GetRecallBudgetMaxOk() (*int32, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.RecallBudgetMax.Get(), o.RecallBudgetMax.IsSet()
|
||||
}
|
||||
|
||||
// HasRecallBudgetMax returns a boolean if a field has been set.
|
||||
func (o *BankTemplateConfig) HasRecallBudgetMax() bool {
|
||||
if o != nil && o.RecallBudgetMax.IsSet() {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetRecallBudgetMax gets a reference to the given NullableInt32 and assigns it to the RecallBudgetMax field.
|
||||
func (o *BankTemplateConfig) SetRecallBudgetMax(v int32) {
|
||||
o.RecallBudgetMax.Set(&v)
|
||||
}
|
||||
// SetRecallBudgetMaxNil sets the value for RecallBudgetMax to be an explicit nil
|
||||
func (o *BankTemplateConfig) SetRecallBudgetMaxNil() {
|
||||
o.RecallBudgetMax.Set(nil)
|
||||
}
|
||||
|
||||
// UnsetRecallBudgetMax ensures that no value is present for RecallBudgetMax, not even an explicit nil
|
||||
func (o *BankTemplateConfig) UnsetRecallBudgetMax() {
|
||||
o.RecallBudgetMax.Unset()
|
||||
}
|
||||
|
||||
func (o BankTemplateConfig) MarshalJSON() ([]byte, error) {
|
||||
toSerialize,err := o.ToMap()
|
||||
if err != nil {
|
||||
@@ -591,6 +1381,63 @@ func (o BankTemplateConfig) ToMap() (map[string]interface{}, error) {
|
||||
if o.EntitiesAllowFreeForm.IsSet() {
|
||||
toSerialize["entities_allow_free_form"] = o.EntitiesAllowFreeForm.Get()
|
||||
}
|
||||
if o.RetainDefaultStrategy.IsSet() {
|
||||
toSerialize["retain_default_strategy"] = o.RetainDefaultStrategy.Get()
|
||||
}
|
||||
if o.RetainStrategies != nil {
|
||||
toSerialize["retain_strategies"] = o.RetainStrategies
|
||||
}
|
||||
if o.RetainChunkBatchSize.IsSet() {
|
||||
toSerialize["retain_chunk_batch_size"] = o.RetainChunkBatchSize.Get()
|
||||
}
|
||||
if o.McpEnabledTools != nil {
|
||||
toSerialize["mcp_enabled_tools"] = o.McpEnabledTools
|
||||
}
|
||||
if o.ConsolidationLlmBatchSize.IsSet() {
|
||||
toSerialize["consolidation_llm_batch_size"] = o.ConsolidationLlmBatchSize.Get()
|
||||
}
|
||||
if o.ConsolidationSourceFactsMaxTokens.IsSet() {
|
||||
toSerialize["consolidation_source_facts_max_tokens"] = o.ConsolidationSourceFactsMaxTokens.Get()
|
||||
}
|
||||
if o.ConsolidationSourceFactsMaxTokensPerObservation.IsSet() {
|
||||
toSerialize["consolidation_source_facts_max_tokens_per_observation"] = o.ConsolidationSourceFactsMaxTokensPerObservation.Get()
|
||||
}
|
||||
if o.MaxObservationsPerScope.IsSet() {
|
||||
toSerialize["max_observations_per_scope"] = o.MaxObservationsPerScope.Get()
|
||||
}
|
||||
if o.ReflectSourceFactsMaxTokens.IsSet() {
|
||||
toSerialize["reflect_source_facts_max_tokens"] = o.ReflectSourceFactsMaxTokens.Get()
|
||||
}
|
||||
if o.LlmGeminiSafetySettings != nil {
|
||||
toSerialize["llm_gemini_safety_settings"] = o.LlmGeminiSafetySettings
|
||||
}
|
||||
if o.RecallBudgetFunction.IsSet() {
|
||||
toSerialize["recall_budget_function"] = o.RecallBudgetFunction.Get()
|
||||
}
|
||||
if o.RecallBudgetFixedLow.IsSet() {
|
||||
toSerialize["recall_budget_fixed_low"] = o.RecallBudgetFixedLow.Get()
|
||||
}
|
||||
if o.RecallBudgetFixedMid.IsSet() {
|
||||
toSerialize["recall_budget_fixed_mid"] = o.RecallBudgetFixedMid.Get()
|
||||
}
|
||||
if o.RecallBudgetFixedHigh.IsSet() {
|
||||
toSerialize["recall_budget_fixed_high"] = o.RecallBudgetFixedHigh.Get()
|
||||
}
|
||||
if o.RecallBudgetAdaptiveLow.IsSet() {
|
||||
toSerialize["recall_budget_adaptive_low"] = o.RecallBudgetAdaptiveLow.Get()
|
||||
}
|
||||
if o.RecallBudgetAdaptiveMid.IsSet() {
|
||||
toSerialize["recall_budget_adaptive_mid"] = o.RecallBudgetAdaptiveMid.Get()
|
||||
}
|
||||
if o.RecallBudgetAdaptiveHigh.IsSet() {
|
||||
toSerialize["recall_budget_adaptive_high"] = o.RecallBudgetAdaptiveHigh.Get()
|
||||
}
|
||||
if o.RecallBudgetMin.IsSet() {
|
||||
toSerialize["recall_budget_min"] = o.RecallBudgetMin.Get()
|
||||
}
|
||||
if o.RecallBudgetMax.IsSet() {
|
||||
toSerialize["recall_budget_max"] = o.RecallBudgetMax.Get()
|
||||
}
|
||||
return toSerialize, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
HTTP API for Hindsight
|
||||
|
||||
The version of the OpenAPI document: 0.5.0
|
||||
The version of the OpenAPI document: 0.5.2
|
||||
Generated by OpenAPI Generator (https://openapi-generator.tech)
|
||||
|
||||
Do not edit the class manually.
|
||||
@@ -17,8 +17,8 @@ import pprint
|
||||
import re # noqa: F401
|
||||
import json
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr
|
||||
from typing import Any, ClassVar, Dict, List, Optional
|
||||
from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictFloat, StrictInt, StrictStr
|
||||
from typing import Any, ClassVar, Dict, List, Optional, Union
|
||||
from typing_extensions import Annotated
|
||||
from typing import Optional, Set
|
||||
from typing_extensions import Self
|
||||
@@ -39,7 +39,26 @@ class BankTemplateConfig(BaseModel):
|
||||
disposition_empathy: Optional[Annotated[int, Field(le=5, strict=True, ge=1)]] = None
|
||||
entity_labels: Optional[List[Dict[str, Any]]] = None
|
||||
entities_allow_free_form: Optional[StrictBool] = None
|
||||
__properties: ClassVar[List[str]] = ["reflect_mission", "retain_mission", "retain_extraction_mode", "retain_custom_instructions", "retain_chunk_size", "enable_observations", "observations_mission", "disposition_skepticism", "disposition_literalism", "disposition_empathy", "entity_labels", "entities_allow_free_form"]
|
||||
retain_default_strategy: Optional[StrictStr] = None
|
||||
retain_strategies: Optional[Dict[str, Any]] = None
|
||||
retain_chunk_batch_size: Optional[StrictInt] = None
|
||||
mcp_enabled_tools: Optional[List[StrictStr]] = None
|
||||
consolidation_llm_batch_size: Optional[StrictInt] = None
|
||||
consolidation_source_facts_max_tokens: Optional[StrictInt] = None
|
||||
consolidation_source_facts_max_tokens_per_observation: Optional[StrictInt] = None
|
||||
max_observations_per_scope: Optional[StrictInt] = None
|
||||
reflect_source_facts_max_tokens: Optional[StrictInt] = None
|
||||
llm_gemini_safety_settings: Optional[List[Any]] = None
|
||||
recall_budget_function: Optional[StrictStr] = None
|
||||
recall_budget_fixed_low: Optional[StrictInt] = None
|
||||
recall_budget_fixed_mid: Optional[StrictInt] = None
|
||||
recall_budget_fixed_high: Optional[StrictInt] = None
|
||||
recall_budget_adaptive_low: Optional[Union[StrictFloat, StrictInt]] = None
|
||||
recall_budget_adaptive_mid: Optional[Union[StrictFloat, StrictInt]] = None
|
||||
recall_budget_adaptive_high: Optional[Union[StrictFloat, StrictInt]] = None
|
||||
recall_budget_min: Optional[StrictInt] = None
|
||||
recall_budget_max: Optional[StrictInt] = None
|
||||
__properties: ClassVar[List[str]] = ["reflect_mission", "retain_mission", "retain_extraction_mode", "retain_custom_instructions", "retain_chunk_size", "enable_observations", "observations_mission", "disposition_skepticism", "disposition_literalism", "disposition_empathy", "entity_labels", "entities_allow_free_form", "retain_default_strategy", "retain_strategies", "retain_chunk_batch_size", "mcp_enabled_tools", "consolidation_llm_batch_size", "consolidation_source_facts_max_tokens", "consolidation_source_facts_max_tokens_per_observation", "max_observations_per_scope", "reflect_source_facts_max_tokens", "llm_gemini_safety_settings", "recall_budget_function", "recall_budget_fixed_low", "recall_budget_fixed_mid", "recall_budget_fixed_high", "recall_budget_adaptive_low", "recall_budget_adaptive_mid", "recall_budget_adaptive_high", "recall_budget_min", "recall_budget_max"]
|
||||
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -140,6 +159,101 @@ class BankTemplateConfig(BaseModel):
|
||||
if self.entities_allow_free_form is None and "entities_allow_free_form" in self.model_fields_set:
|
||||
_dict['entities_allow_free_form'] = None
|
||||
|
||||
# set to None if retain_default_strategy (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.retain_default_strategy is None and "retain_default_strategy" in self.model_fields_set:
|
||||
_dict['retain_default_strategy'] = None
|
||||
|
||||
# set to None if retain_strategies (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.retain_strategies is None and "retain_strategies" in self.model_fields_set:
|
||||
_dict['retain_strategies'] = None
|
||||
|
||||
# set to None if retain_chunk_batch_size (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.retain_chunk_batch_size is None and "retain_chunk_batch_size" in self.model_fields_set:
|
||||
_dict['retain_chunk_batch_size'] = None
|
||||
|
||||
# set to None if mcp_enabled_tools (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.mcp_enabled_tools is None and "mcp_enabled_tools" in self.model_fields_set:
|
||||
_dict['mcp_enabled_tools'] = None
|
||||
|
||||
# set to None if consolidation_llm_batch_size (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.consolidation_llm_batch_size is None and "consolidation_llm_batch_size" in self.model_fields_set:
|
||||
_dict['consolidation_llm_batch_size'] = None
|
||||
|
||||
# set to None if consolidation_source_facts_max_tokens (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.consolidation_source_facts_max_tokens is None and "consolidation_source_facts_max_tokens" in self.model_fields_set:
|
||||
_dict['consolidation_source_facts_max_tokens'] = None
|
||||
|
||||
# set to None if consolidation_source_facts_max_tokens_per_observation (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.consolidation_source_facts_max_tokens_per_observation is None and "consolidation_source_facts_max_tokens_per_observation" in self.model_fields_set:
|
||||
_dict['consolidation_source_facts_max_tokens_per_observation'] = None
|
||||
|
||||
# set to None if max_observations_per_scope (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.max_observations_per_scope is None and "max_observations_per_scope" in self.model_fields_set:
|
||||
_dict['max_observations_per_scope'] = None
|
||||
|
||||
# set to None if reflect_source_facts_max_tokens (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.reflect_source_facts_max_tokens is None and "reflect_source_facts_max_tokens" in self.model_fields_set:
|
||||
_dict['reflect_source_facts_max_tokens'] = None
|
||||
|
||||
# set to None if llm_gemini_safety_settings (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.llm_gemini_safety_settings is None and "llm_gemini_safety_settings" in self.model_fields_set:
|
||||
_dict['llm_gemini_safety_settings'] = None
|
||||
|
||||
# set to None if recall_budget_function (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_function is None and "recall_budget_function" in self.model_fields_set:
|
||||
_dict['recall_budget_function'] = None
|
||||
|
||||
# set to None if recall_budget_fixed_low (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_fixed_low is None and "recall_budget_fixed_low" in self.model_fields_set:
|
||||
_dict['recall_budget_fixed_low'] = None
|
||||
|
||||
# set to None if recall_budget_fixed_mid (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_fixed_mid is None and "recall_budget_fixed_mid" in self.model_fields_set:
|
||||
_dict['recall_budget_fixed_mid'] = None
|
||||
|
||||
# set to None if recall_budget_fixed_high (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_fixed_high is None and "recall_budget_fixed_high" in self.model_fields_set:
|
||||
_dict['recall_budget_fixed_high'] = None
|
||||
|
||||
# set to None if recall_budget_adaptive_low (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_adaptive_low is None and "recall_budget_adaptive_low" in self.model_fields_set:
|
||||
_dict['recall_budget_adaptive_low'] = None
|
||||
|
||||
# set to None if recall_budget_adaptive_mid (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_adaptive_mid is None and "recall_budget_adaptive_mid" in self.model_fields_set:
|
||||
_dict['recall_budget_adaptive_mid'] = None
|
||||
|
||||
# set to None if recall_budget_adaptive_high (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_adaptive_high is None and "recall_budget_adaptive_high" in self.model_fields_set:
|
||||
_dict['recall_budget_adaptive_high'] = None
|
||||
|
||||
# set to None if recall_budget_min (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_min is None and "recall_budget_min" in self.model_fields_set:
|
||||
_dict['recall_budget_min'] = None
|
||||
|
||||
# set to None if recall_budget_max (nullable) is None
|
||||
# and model_fields_set contains the field
|
||||
if self.recall_budget_max is None and "recall_budget_max" in self.model_fields_set:
|
||||
_dict['recall_budget_max'] = None
|
||||
|
||||
return _dict
|
||||
|
||||
@classmethod
|
||||
@@ -163,7 +277,26 @@ class BankTemplateConfig(BaseModel):
|
||||
"disposition_literalism": obj.get("disposition_literalism"),
|
||||
"disposition_empathy": obj.get("disposition_empathy"),
|
||||
"entity_labels": obj.get("entity_labels"),
|
||||
"entities_allow_free_form": obj.get("entities_allow_free_form")
|
||||
"entities_allow_free_form": obj.get("entities_allow_free_form"),
|
||||
"retain_default_strategy": obj.get("retain_default_strategy"),
|
||||
"retain_strategies": obj.get("retain_strategies"),
|
||||
"retain_chunk_batch_size": obj.get("retain_chunk_batch_size"),
|
||||
"mcp_enabled_tools": obj.get("mcp_enabled_tools"),
|
||||
"consolidation_llm_batch_size": obj.get("consolidation_llm_batch_size"),
|
||||
"consolidation_source_facts_max_tokens": obj.get("consolidation_source_facts_max_tokens"),
|
||||
"consolidation_source_facts_max_tokens_per_observation": obj.get("consolidation_source_facts_max_tokens_per_observation"),
|
||||
"max_observations_per_scope": obj.get("max_observations_per_scope"),
|
||||
"reflect_source_facts_max_tokens": obj.get("reflect_source_facts_max_tokens"),
|
||||
"llm_gemini_safety_settings": obj.get("llm_gemini_safety_settings"),
|
||||
"recall_budget_function": obj.get("recall_budget_function"),
|
||||
"recall_budget_fixed_low": obj.get("recall_budget_fixed_low"),
|
||||
"recall_budget_fixed_mid": obj.get("recall_budget_fixed_mid"),
|
||||
"recall_budget_fixed_high": obj.get("recall_budget_fixed_high"),
|
||||
"recall_budget_adaptive_low": obj.get("recall_budget_adaptive_low"),
|
||||
"recall_budget_adaptive_mid": obj.get("recall_budget_adaptive_mid"),
|
||||
"recall_budget_adaptive_high": obj.get("recall_budget_adaptive_high"),
|
||||
"recall_budget_min": obj.get("recall_budget_min"),
|
||||
"recall_budget_max": obj.get("recall_budget_max")
|
||||
})
|
||||
return _obj
|
||||
|
||||
|
||||
@@ -365,6 +365,14 @@ export type BankStatsResponse = {
|
||||
* Failed Operations
|
||||
*/
|
||||
failed_operations: number;
|
||||
/**
|
||||
* Operations By Status
|
||||
*
|
||||
* Async operations grouped by status (pending, in_progress, completed, failed, cancelled).
|
||||
*/
|
||||
operations_by_status?: {
|
||||
[key: string]: number;
|
||||
};
|
||||
/**
|
||||
* Last Consolidated At
|
||||
*
|
||||
@@ -377,6 +385,12 @@ export type BankStatsResponse = {
|
||||
* Number of memories not yet processed into observations
|
||||
*/
|
||||
pending_consolidation?: number;
|
||||
/**
|
||||
* Failed Consolidation
|
||||
*
|
||||
* Number of source memories (world/experience) whose consolidation permanently failed and can be retried via the consolidation recovery endpoint.
|
||||
*/
|
||||
failed_consolidation?: number;
|
||||
/**
|
||||
* Total Observations
|
||||
*
|
||||
@@ -468,6 +482,122 @@ export type BankTemplateConfig = {
|
||||
* Allow entities outside the label vocabulary
|
||||
*/
|
||||
entities_allow_free_form?: boolean | null;
|
||||
/**
|
||||
* Retain Default Strategy
|
||||
*
|
||||
* Name of the default retain strategy (key into retain_strategies map)
|
||||
*/
|
||||
retain_default_strategy?: string | null;
|
||||
/**
|
||||
* Retain Strategies
|
||||
*
|
||||
* Map of retain strategy name to per-strategy config dict
|
||||
*/
|
||||
retain_strategies?: {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
/**
|
||||
* Retain Chunk Batch Size
|
||||
*
|
||||
* Max chunks per streaming batch (0 disables batching)
|
||||
*/
|
||||
retain_chunk_batch_size?: number | null;
|
||||
/**
|
||||
* Mcp Enabled Tools
|
||||
*
|
||||
* MCP tool allowlist for this bank (None = all tools)
|
||||
*/
|
||||
mcp_enabled_tools?: Array<string> | null;
|
||||
/**
|
||||
* Consolidation Llm Batch Size
|
||||
*
|
||||
* LLM batch size for observation consolidation
|
||||
*/
|
||||
consolidation_llm_batch_size?: number | null;
|
||||
/**
|
||||
* Consolidation Source Facts Max Tokens
|
||||
*
|
||||
* Max tokens of source facts per consolidation batch
|
||||
*/
|
||||
consolidation_source_facts_max_tokens?: number | null;
|
||||
/**
|
||||
* Consolidation Source Facts Max Tokens Per Observation
|
||||
*
|
||||
* Max tokens of source facts per observation
|
||||
*/
|
||||
consolidation_source_facts_max_tokens_per_observation?: number | null;
|
||||
/**
|
||||
* Max Observations Per Scope
|
||||
*
|
||||
* Max observations to retain per consolidation scope
|
||||
*/
|
||||
max_observations_per_scope?: number | null;
|
||||
/**
|
||||
* Reflect Source Facts Max Tokens
|
||||
*
|
||||
* Max tokens of source facts per reflect call
|
||||
*/
|
||||
reflect_source_facts_max_tokens?: number | null;
|
||||
/**
|
||||
* Llm Gemini Safety Settings
|
||||
*
|
||||
* Per-bank Gemini/VertexAI safety filter settings
|
||||
*/
|
||||
llm_gemini_safety_settings?: Array<unknown> | null;
|
||||
/**
|
||||
* Recall Budget Function
|
||||
*
|
||||
* Recall budget mapping function: 'fixed' or 'adaptive'
|
||||
*/
|
||||
recall_budget_function?: string | null;
|
||||
/**
|
||||
* Recall Budget Fixed Low
|
||||
*
|
||||
* Fixed thinking_budget for budget=low (function='fixed')
|
||||
*/
|
||||
recall_budget_fixed_low?: number | null;
|
||||
/**
|
||||
* Recall Budget Fixed Mid
|
||||
*
|
||||
* Fixed thinking_budget for budget=mid (function='fixed')
|
||||
*/
|
||||
recall_budget_fixed_mid?: number | null;
|
||||
/**
|
||||
* Recall Budget Fixed High
|
||||
*
|
||||
* Fixed thinking_budget for budget=high (function='fixed')
|
||||
*/
|
||||
recall_budget_fixed_high?: number | null;
|
||||
/**
|
||||
* Recall Budget Adaptive Low
|
||||
*
|
||||
* Ratio of max_tokens for budget=low (function='adaptive')
|
||||
*/
|
||||
recall_budget_adaptive_low?: number | null;
|
||||
/**
|
||||
* Recall Budget Adaptive Mid
|
||||
*
|
||||
* Ratio of max_tokens for budget=mid (function='adaptive')
|
||||
*/
|
||||
recall_budget_adaptive_mid?: number | null;
|
||||
/**
|
||||
* Recall Budget Adaptive High
|
||||
*
|
||||
* Ratio of max_tokens for budget=high (function='adaptive')
|
||||
*/
|
||||
recall_budget_adaptive_high?: number | null;
|
||||
/**
|
||||
* Recall Budget Min
|
||||
*
|
||||
* Floor for the adaptive function (after clamping)
|
||||
*/
|
||||
recall_budget_min?: number | null;
|
||||
/**
|
||||
* Recall Budget Max
|
||||
*
|
||||
* Ceiling for the adaptive function (after clamping)
|
||||
*/
|
||||
recall_budget_max?: number | null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1267,6 +1397,38 @@ export type EntityDetailResponse = {
|
||||
observations: Array<EntityObservationResponse>;
|
||||
};
|
||||
|
||||
/**
|
||||
* EntityGraphResponse
|
||||
*
|
||||
* Response model for entity co-occurrence graph endpoint.
|
||||
*/
|
||||
export type EntityGraphResponse = {
|
||||
/**
|
||||
* Nodes
|
||||
*/
|
||||
nodes: Array<{
|
||||
[key: string]: unknown;
|
||||
}>;
|
||||
/**
|
||||
* Edges
|
||||
*/
|
||||
edges: Array<{
|
||||
[key: string]: unknown;
|
||||
}>;
|
||||
/**
|
||||
* Total Entities
|
||||
*/
|
||||
total_entities: number;
|
||||
/**
|
||||
* Total Edges
|
||||
*/
|
||||
total_edges: number;
|
||||
/**
|
||||
* Limit
|
||||
*/
|
||||
limit: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* EntityIncludeOptions
|
||||
*
|
||||
@@ -1596,6 +1758,36 @@ export type ListTagsResponse = {
|
||||
offset: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* MemoriesTimeseriesResponse
|
||||
*
|
||||
* Time-series of memory ingestion bucketed by time and fact type.
|
||||
*/
|
||||
export type MemoriesTimeseriesResponse = {
|
||||
/**
|
||||
* Bank Id
|
||||
*/
|
||||
bank_id: string;
|
||||
/**
|
||||
* Period
|
||||
*
|
||||
* One of: 1h, 12h, 1d, 7d, 30d, 90d.
|
||||
*/
|
||||
period: string;
|
||||
/**
|
||||
* Trunc
|
||||
*
|
||||
* Bucket granularity: minute, hour, day.
|
||||
*/
|
||||
trunc: string;
|
||||
/**
|
||||
* Buckets
|
||||
*
|
||||
* Per-bucket counts, always returned fully padded for the requested period.
|
||||
*/
|
||||
buckets?: Array<MemoryTimeseriesBucket>;
|
||||
};
|
||||
|
||||
/**
|
||||
* MemoryItem
|
||||
*
|
||||
@@ -1665,6 +1857,38 @@ export type MemoryItem = {
|
||||
update_mode?: "replace" | "append" | null;
|
||||
};
|
||||
|
||||
/**
|
||||
* MemoryTimeseriesBucket
|
||||
*
|
||||
* One bucket in the memory ingestion time-series.
|
||||
*/
|
||||
export type MemoryTimeseriesBucket = {
|
||||
/**
|
||||
* Time
|
||||
*
|
||||
* Bucket start timestamp in ISO-8601 (UTC).
|
||||
*/
|
||||
time: string;
|
||||
/**
|
||||
* World
|
||||
*
|
||||
* World-fact memories ingested in this bucket.
|
||||
*/
|
||||
world?: number;
|
||||
/**
|
||||
* Experience
|
||||
*
|
||||
* Experience memories ingested in this bucket.
|
||||
*/
|
||||
experience?: number;
|
||||
/**
|
||||
* Observation
|
||||
*
|
||||
* Observations recorded in this bucket.
|
||||
*/
|
||||
observation?: number;
|
||||
};
|
||||
|
||||
/**
|
||||
* MentalModelListResponse
|
||||
*
|
||||
@@ -1730,6 +1954,12 @@ export type MentalModelResponse = {
|
||||
reflect_response?: {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
/**
|
||||
* Is Stale
|
||||
*
|
||||
* True when new memories matching this mental model's tag/fact_type scope have been ingested since last_refreshed_at, or consolidation has pending items. Only populated when detail=full.
|
||||
*/
|
||||
is_stale?: boolean | null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1776,6 +2006,24 @@ export type MentalModelTriggerInput = {
|
||||
tag_groups?: Array<
|
||||
TagGroupLeaf | TagGroupAndInput | TagGroupOrInput | TagGroupNotInput
|
||||
> | null;
|
||||
/**
|
||||
* Include Chunks
|
||||
*
|
||||
* Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks).
|
||||
*/
|
||||
include_chunks?: boolean | null;
|
||||
/**
|
||||
* Recall Max Tokens
|
||||
*
|
||||
* Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens).
|
||||
*/
|
||||
recall_max_tokens?: number | null;
|
||||
/**
|
||||
* Recall Chunks Max Tokens
|
||||
*
|
||||
* Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens).
|
||||
*/
|
||||
recall_chunks_max_tokens?: number | null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1822,6 +2070,24 @@ export type MentalModelTriggerOutput = {
|
||||
tag_groups?: Array<
|
||||
TagGroupLeaf | TagGroupAndOutput | TagGroupOrOutput | TagGroupNotOutput
|
||||
> | null;
|
||||
/**
|
||||
* Include Chunks
|
||||
*
|
||||
* Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks).
|
||||
*/
|
||||
include_chunks?: boolean | null;
|
||||
/**
|
||||
* Recall Max Tokens
|
||||
*
|
||||
* Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens).
|
||||
*/
|
||||
recall_max_tokens?: number | null;
|
||||
/**
|
||||
* Recall Chunks Max Tokens
|
||||
*
|
||||
* Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens).
|
||||
*/
|
||||
recall_chunks_max_tokens?: number | null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1908,6 +2174,14 @@ export type OperationStatusResponse = {
|
||||
* Child operations for batch operations (if applicable)
|
||||
*/
|
||||
child_operations?: Array<ChildOperationStatus> | null;
|
||||
/**
|
||||
* Task Payload
|
||||
*
|
||||
* Raw task payload (params the operation was submitted with). Only populated when include_payload=true.
|
||||
*/
|
||||
task_payload?: {
|
||||
[key: string]: unknown;
|
||||
} | null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -3185,6 +3459,10 @@ export type ListMemoriesData = {
|
||||
* Q
|
||||
*/
|
||||
q?: string | null;
|
||||
/**
|
||||
* Consolidation State
|
||||
*/
|
||||
consolidation_state?: string | null;
|
||||
/**
|
||||
* Limit
|
||||
*/
|
||||
@@ -3435,6 +3713,49 @@ export type GetAgentStatsResponses = {
|
||||
export type GetAgentStatsResponse =
|
||||
GetAgentStatsResponses[keyof GetAgentStatsResponses];
|
||||
|
||||
export type GetMemoriesTimeseriesData = {
|
||||
body?: never;
|
||||
headers?: {
|
||||
/**
|
||||
* Authorization
|
||||
*/
|
||||
authorization?: string | null;
|
||||
};
|
||||
path: {
|
||||
/**
|
||||
* Bank Id
|
||||
*/
|
||||
bank_id: string;
|
||||
};
|
||||
query?: {
|
||||
/**
|
||||
* Period
|
||||
*/
|
||||
period?: string;
|
||||
};
|
||||
url: "/v1/default/banks/{bank_id}/stats/memories-timeseries";
|
||||
};
|
||||
|
||||
export type GetMemoriesTimeseriesErrors = {
|
||||
/**
|
||||
* Validation Error
|
||||
*/
|
||||
422: HttpValidationError;
|
||||
};
|
||||
|
||||
export type GetMemoriesTimeseriesError =
|
||||
GetMemoriesTimeseriesErrors[keyof GetMemoriesTimeseriesErrors];
|
||||
|
||||
export type GetMemoriesTimeseriesResponses = {
|
||||
/**
|
||||
* Successful Response
|
||||
*/
|
||||
200: MemoriesTimeseriesResponse;
|
||||
};
|
||||
|
||||
export type GetMemoriesTimeseriesResponse =
|
||||
GetMemoriesTimeseriesResponses[keyof GetMemoriesTimeseriesResponses];
|
||||
|
||||
export type ListEntitiesData = {
|
||||
body?: never;
|
||||
headers?: {
|
||||
@@ -3485,6 +3806,57 @@ export type ListEntitiesResponses = {
|
||||
export type ListEntitiesResponse =
|
||||
ListEntitiesResponses[keyof ListEntitiesResponses];
|
||||
|
||||
export type GetEntityGraphData = {
|
||||
body?: never;
|
||||
headers?: {
|
||||
/**
|
||||
* Authorization
|
||||
*/
|
||||
authorization?: string | null;
|
||||
};
|
||||
path: {
|
||||
/**
|
||||
* Bank Id
|
||||
*/
|
||||
bank_id: string;
|
||||
};
|
||||
query?: {
|
||||
/**
|
||||
* Limit
|
||||
*
|
||||
* Maximum number of co-occurrence edges to return
|
||||
*/
|
||||
limit?: number;
|
||||
/**
|
||||
* Min Count
|
||||
*
|
||||
* Minimum cooccurrence_count to include an edge
|
||||
*/
|
||||
min_count?: number;
|
||||
};
|
||||
url: "/v1/default/banks/{bank_id}/entities/graph";
|
||||
};
|
||||
|
||||
export type GetEntityGraphErrors = {
|
||||
/**
|
||||
* Validation Error
|
||||
*/
|
||||
422: HttpValidationError;
|
||||
};
|
||||
|
||||
export type GetEntityGraphError =
|
||||
GetEntityGraphErrors[keyof GetEntityGraphErrors];
|
||||
|
||||
export type GetEntityGraphResponses = {
|
||||
/**
|
||||
* Successful Response
|
||||
*/
|
||||
200: EntityGraphResponse;
|
||||
};
|
||||
|
||||
export type GetEntityGraphResponse =
|
||||
GetEntityGraphResponses[keyof GetEntityGraphResponses];
|
||||
|
||||
export type GetEntityData = {
|
||||
body?: never;
|
||||
headers?: {
|
||||
@@ -4509,7 +4881,14 @@ export type GetOperationStatusData = {
|
||||
*/
|
||||
operation_id: string;
|
||||
};
|
||||
query?: never;
|
||||
query?: {
|
||||
/**
|
||||
* Include Payload
|
||||
*
|
||||
* Include the raw task payload (submission params) in the response. May be large.
|
||||
*/
|
||||
include_payload?: boolean;
|
||||
};
|
||||
url: "/v1/default/banks/{bank_id}/operations/{operation_id}";
|
||||
};
|
||||
|
||||
|
||||
@@ -269,6 +269,40 @@ Controls content filtering thresholds for Gemini and VertexAI providers. Accepts
|
||||
|
||||
Only applies when `HINDSIGHT_API_LLM_PROVIDER` is `gemini` or `vertexai`.
|
||||
|
||||
### recall_budget_function {#recall-budget-configuration}
|
||||
|
||||
Selects how the [`recall` request's `budget` parameter](./recall) (`low` / `mid` / `high`) maps to the internal `thinking_budget` integer used by every retrieval method (semantic, BM25, graph, temporal). Two functions are supported:
|
||||
|
||||
| Function | Behaviour |
|
||||
|----------|-----------|
|
||||
| `fixed` *(default)* | `thinking_budget = recall_budget_fixed_<level>` — independent of `max_tokens`. Preserves legacy behavior. |
|
||||
| `adaptive` | `thinking_budget = round(max_tokens * recall_budget_adaptive_<level>)`, clamped to `[recall_budget_min, recall_budget_max]`. Retrieval breadth scales with the requested output size. |
|
||||
|
||||
```json
|
||||
{
|
||||
"recall_budget_function": "adaptive",
|
||||
"recall_budget_adaptive_low": 0.05,
|
||||
"recall_budget_adaptive_mid": 0.1,
|
||||
"recall_budget_adaptive_high": 0.3,
|
||||
"recall_budget_min": 30,
|
||||
"recall_budget_max": 1500
|
||||
}
|
||||
```
|
||||
|
||||
### recall_budget_fixed_low / recall_budget_fixed_mid / recall_budget_fixed_high
|
||||
|
||||
When `recall_budget_function` is `fixed` (the default), these positive integers are used directly as the per-method retrieval limit for each `budget` level. Defaults: `100` / `300` / `1000` — exactly matching the legacy hardcoded mapping.
|
||||
|
||||
### recall_budget_adaptive_low / recall_budget_adaptive_mid / recall_budget_adaptive_high
|
||||
|
||||
When `recall_budget_function` is `adaptive`, these positive ratios multiply the request's `max_tokens` to derive the per-method retrieval limit. Defaults: `0.025` / `0.075` / `0.25` — chosen to roughly match the fixed defaults at `max_tokens = 4096`.
|
||||
|
||||
### recall_budget_min / recall_budget_max
|
||||
|
||||
Floor and ceiling applied to the result of the adaptive function (after the ratio multiplication). Both must be positive integers and `min ≤ max`. Defaults: `20` / `2000`.
|
||||
|
||||
See [Recall budget mapping](/developer/configuration#recall-budget-mapping) for environment variable names and full defaults.
|
||||
|
||||
---
|
||||
|
||||
## Updating Configuration
|
||||
|
||||
@@ -685,6 +685,27 @@ For advanced authentication (JWT, OAuth, multi-tenant schemas), implement a cust
|
||||
|
||||
- **`link_expansion`** (default): Fast graph expansion from semantic seeds via entity co-occurrence, semantic kNN, and causal links. Target latency under 100ms.
|
||||
|
||||
#### Recall budget mapping
|
||||
|
||||
The recall request takes a `budget` parameter (`low` / `mid` / `high`, default `mid`) that maps to an integer `thinking_budget` used by every retrieval method (semantic, BM25, graph, temporal). These knobs control that mapping. They are hierarchical — overridable per bank via the [config API](#hierarchical-configuration).
|
||||
|
||||
Two functions are available:
|
||||
|
||||
- **`fixed`** (default — preserves legacy behavior): `thinking_budget = recall_budget_fixed_<level>` (independent of `max_tokens`).
|
||||
- **`adaptive`**: `thinking_budget = round(max_tokens * recall_budget_adaptive_<level>)`, clamped to `[recall_budget_min, recall_budget_max]`. Useful when callers vary `max_tokens` and you want retrieval breadth to scale with the requested output size.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FUNCTION` | Mapping function: `fixed` or `adaptive`. | `fixed` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FIXED_LOW` | Items per retrieval method per fact type when `budget=low` and function is `fixed`. | `100` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FIXED_MID` | Items per retrieval method per fact type when `budget=mid` and function is `fixed`. | `300` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FIXED_HIGH` | Items per retrieval method per fact type when `budget=high` and function is `fixed`. | `1000` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_LOW` | Ratio of request `max_tokens` used when `budget=low` and function is `adaptive`. | `0.025` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_MID` | Ratio of request `max_tokens` used when `budget=mid` and function is `adaptive`. | `0.075` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_HIGH` | Ratio of request `max_tokens` used when `budget=high` and function is `adaptive`. | `0.25` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_MIN` | Floor for the adaptive function (after clamping). | `20` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_MAX` | Ceiling for the adaptive function (after clamping). | `2000` |
|
||||
|
||||
### Retain
|
||||
|
||||
Controls the retain (memory ingestion) pipeline.
|
||||
|
||||
@@ -125,6 +125,30 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "rag",
|
||||
"name": "RAG Mode",
|
||||
"description": "Low-latency retrieval-only mode. Stores raw chunks without LLM processing and retrieves via semantic + BM25 search only. No fact extraction, no observations, no graph traversal, no temporal filtering, no reranking.",
|
||||
"category": "retrieval",
|
||||
"integrations": [
|
||||
"litellm",
|
||||
"langgraph",
|
||||
"pydantic-ai",
|
||||
"ai-sdk",
|
||||
"llamaindex",
|
||||
"local-mcp"
|
||||
],
|
||||
"manifest": {
|
||||
"version": "1",
|
||||
"bank": {
|
||||
"retain_extraction_mode": "chunks",
|
||||
"enable_observations": false,
|
||||
"enable_temporal_extraction": false,
|
||||
"enable_graph_retrieval": false,
|
||||
"enable_reranking": false
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import templatesData from '@site/src/data/templates.json';
|
||||
import integrationsData from '@site/src/data/integrations.json';
|
||||
import styles from './index.module.css';
|
||||
|
||||
const CATEGORIES = ['all', 'chat', 'coding', 'assistant'] as const;
|
||||
const CATEGORIES = ['all', 'chat', 'coding', 'assistant', 'retrieval'] as const;
|
||||
type Category = (typeof CATEGORIES)[number];
|
||||
|
||||
const CATEGORY_LABELS: Record<Category, string> = {
|
||||
@@ -13,6 +13,7 @@ const CATEGORY_LABELS: Record<Category, string> = {
|
||||
chat: 'Chat',
|
||||
coding: 'Coding',
|
||||
assistant: 'Assistant',
|
||||
retrieval: 'Retrieval',
|
||||
};
|
||||
|
||||
// Build a lookup from integration ID to icon path and name
|
||||
|
||||
@@ -143,7 +143,8 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
@@ -167,6 +168,258 @@
|
||||
"default": null,
|
||||
"description": "Allow entities outside the label vocabulary",
|
||||
"title": "Entities Allow Free Form"
|
||||
},
|
||||
"retain_default_strategy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Name of the default retain strategy (key into retain_strategies map)",
|
||||
"title": "Retain Default Strategy"
|
||||
},
|
||||
"retain_strategies": {
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Map of retain strategy name to per-strategy config dict",
|
||||
"title": "Retain Strategies"
|
||||
},
|
||||
"retain_chunk_batch_size": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Max chunks per streaming batch (0 disables batching)",
|
||||
"title": "Retain Chunk Batch Size"
|
||||
},
|
||||
"mcp_enabled_tools": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "MCP tool allowlist for this bank (None = all tools)",
|
||||
"title": "Mcp Enabled Tools"
|
||||
},
|
||||
"consolidation_llm_batch_size": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "LLM batch size for observation consolidation",
|
||||
"title": "Consolidation Llm Batch Size"
|
||||
},
|
||||
"consolidation_source_facts_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Max tokens of source facts per consolidation batch",
|
||||
"title": "Consolidation Source Facts Max Tokens"
|
||||
},
|
||||
"consolidation_source_facts_max_tokens_per_observation": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Max tokens of source facts per observation",
|
||||
"title": "Consolidation Source Facts Max Tokens Per Observation"
|
||||
},
|
||||
"max_observations_per_scope": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Max observations to retain per consolidation scope",
|
||||
"title": "Max Observations Per Scope"
|
||||
},
|
||||
"reflect_source_facts_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Max tokens of source facts per reflect call",
|
||||
"title": "Reflect Source Facts Max Tokens"
|
||||
},
|
||||
"llm_gemini_safety_settings": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Per-bank Gemini/VertexAI safety filter settings",
|
||||
"title": "Llm Gemini Safety Settings"
|
||||
},
|
||||
"recall_budget_function": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Recall budget mapping function: 'fixed' or 'adaptive'",
|
||||
"title": "Recall Budget Function"
|
||||
},
|
||||
"recall_budget_fixed_low": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Fixed thinking_budget for budget=low (function='fixed')",
|
||||
"title": "Recall Budget Fixed Low"
|
||||
},
|
||||
"recall_budget_fixed_mid": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Fixed thinking_budget for budget=mid (function='fixed')",
|
||||
"title": "Recall Budget Fixed Mid"
|
||||
},
|
||||
"recall_budget_fixed_high": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Fixed thinking_budget for budget=high (function='fixed')",
|
||||
"title": "Recall Budget Fixed High"
|
||||
},
|
||||
"recall_budget_adaptive_low": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Ratio of max_tokens for budget=low (function='adaptive')",
|
||||
"title": "Recall Budget Adaptive Low"
|
||||
},
|
||||
"recall_budget_adaptive_mid": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Ratio of max_tokens for budget=mid (function='adaptive')",
|
||||
"title": "Recall Budget Adaptive Mid"
|
||||
},
|
||||
"recall_budget_adaptive_high": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Ratio of max_tokens for budget=high (function='adaptive')",
|
||||
"title": "Recall Budget Adaptive High"
|
||||
},
|
||||
"recall_budget_min": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Floor for the adaptive function (after clamping)",
|
||||
"title": "Recall Budget Min"
|
||||
},
|
||||
"recall_budget_max": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Ceiling for the adaptive function (after clamping)",
|
||||
"title": "Recall Budget Max"
|
||||
}
|
||||
},
|
||||
"title": "BankTemplateConfig",
|
||||
@@ -362,6 +615,45 @@
|
||||
"default": null,
|
||||
"description": "Compound boolean tag expressions to use during refresh instead of the model's own tags. When set, these tag groups are passed to reflect and the model's flat tags are NOT used for filtering. Supports nested and/or/not expressions for complex tag-based scoping.",
|
||||
"title": "Tag Groups"
|
||||
},
|
||||
"include_chunks": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks).",
|
||||
"title": "Include Chunks"
|
||||
},
|
||||
"recall_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens).",
|
||||
"title": "Recall Max Tokens"
|
||||
},
|
||||
"recall_chunks_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"description": "Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens).",
|
||||
"title": "Recall Chunks Max Tokens"
|
||||
}
|
||||
},
|
||||
"title": "MentalModelTrigger",
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"name": "Apache 2.0",
|
||||
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
},
|
||||
"version": "0.5.0"
|
||||
"version": "0.5.2"
|
||||
},
|
||||
"paths": {
|
||||
"/health": {
|
||||
@@ -255,6 +255,22 @@
|
||||
"title": "Q"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "consolidation_state",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation State"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
@@ -695,6 +711,75 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/stats/memories-timeseries": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Banks"
|
||||
],
|
||||
"summary": "Memory ingestion time-series",
|
||||
"description": "Memories ingested over a period, bucketed by time and broken down by fact type.",
|
||||
"operationId": "get_memories_timeseries",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bank_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Bank Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "period",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": "7d",
|
||||
"title": "Period"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "authorization",
|
||||
"in": "header",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MemoriesTimeseriesResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/entities": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -778,6 +863,89 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/entities/graph": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Entities"
|
||||
],
|
||||
"summary": "Get entity co-occurrence graph",
|
||||
"description": "Return a graph of entities (nodes) and their co-occurrences (edges) for visualization.",
|
||||
"operationId": "get_entity_graph",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bank_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Bank Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"description": "Maximum number of co-occurrence edges to return",
|
||||
"default": 1000,
|
||||
"title": "Limit"
|
||||
},
|
||||
"description": "Maximum number of co-occurrence edges to return"
|
||||
},
|
||||
{
|
||||
"name": "min_count",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"description": "Minimum cooccurrence_count to include an edge",
|
||||
"default": 1,
|
||||
"title": "Min Count"
|
||||
},
|
||||
"description": "Minimum cooccurrence_count to include an edge"
|
||||
},
|
||||
{
|
||||
"name": "authorization",
|
||||
"in": "header",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/EntityGraphResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/entities/{entity_id}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -2534,6 +2702,18 @@
|
||||
"title": "Operation Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "include_payload",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"description": "Include the raw task payload (submission params) in the response. May be large.",
|
||||
"default": false,
|
||||
"title": "Include Payload"
|
||||
},
|
||||
"description": "Include the raw task payload (submission params) in the response. May be large."
|
||||
},
|
||||
{
|
||||
"name": "authorization",
|
||||
"in": "header",
|
||||
@@ -5069,6 +5249,14 @@
|
||||
"type": "integer",
|
||||
"title": "Failed Operations"
|
||||
},
|
||||
"operations_by_status": {
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
},
|
||||
"type": "object",
|
||||
"title": "Operations By Status",
|
||||
"description": "Async operations grouped by status (pending, in_progress, completed, failed, cancelled)."
|
||||
},
|
||||
"last_consolidated_at": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -5087,6 +5275,12 @@
|
||||
"description": "Number of memories not yet processed into observations",
|
||||
"default": 0
|
||||
},
|
||||
"failed_consolidation": {
|
||||
"type": "integer",
|
||||
"title": "Failed Consolidation",
|
||||
"description": "Number of source memories (world/experience) whose consolidation permanently failed and can be retried via the consolidation recovery endpoint.",
|
||||
"default": 0
|
||||
},
|
||||
"total_observations": {
|
||||
"type": "integer",
|
||||
"title": "Total Observations",
|
||||
@@ -5111,6 +5305,7 @@
|
||||
"description": "Response model for bank statistics endpoint.",
|
||||
"example": {
|
||||
"bank_id": "user123",
|
||||
"failed_consolidation": 0,
|
||||
"failed_operations": 0,
|
||||
"last_consolidated_at": "2024-01-15T10:30:00Z",
|
||||
"links_breakdown": {
|
||||
@@ -5298,6 +5493,239 @@
|
||||
],
|
||||
"title": "Entities Allow Free Form",
|
||||
"description": "Allow entities outside the label vocabulary"
|
||||
},
|
||||
"retain_default_strategy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Retain Default Strategy",
|
||||
"description": "Name of the default retain strategy (key into retain_strategies map)"
|
||||
},
|
||||
"retain_strategies": {
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Retain Strategies",
|
||||
"description": "Map of retain strategy name to per-strategy config dict"
|
||||
},
|
||||
"retain_chunk_batch_size": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Retain Chunk Batch Size",
|
||||
"description": "Max chunks per streaming batch (0 disables batching)"
|
||||
},
|
||||
"mcp_enabled_tools": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Mcp Enabled Tools",
|
||||
"description": "MCP tool allowlist for this bank (None = all tools)"
|
||||
},
|
||||
"consolidation_llm_batch_size": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation Llm Batch Size",
|
||||
"description": "LLM batch size for observation consolidation"
|
||||
},
|
||||
"consolidation_source_facts_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation Source Facts Max Tokens",
|
||||
"description": "Max tokens of source facts per consolidation batch"
|
||||
},
|
||||
"consolidation_source_facts_max_tokens_per_observation": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation Source Facts Max Tokens Per Observation",
|
||||
"description": "Max tokens of source facts per observation"
|
||||
},
|
||||
"max_observations_per_scope": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Max Observations Per Scope",
|
||||
"description": "Max observations to retain per consolidation scope"
|
||||
},
|
||||
"reflect_source_facts_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Reflect Source Facts Max Tokens",
|
||||
"description": "Max tokens of source facts per reflect call"
|
||||
},
|
||||
"llm_gemini_safety_settings": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Llm Gemini Safety Settings",
|
||||
"description": "Per-bank Gemini/VertexAI safety filter settings"
|
||||
},
|
||||
"recall_budget_function": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Function",
|
||||
"description": "Recall budget mapping function: 'fixed' or 'adaptive'"
|
||||
},
|
||||
"recall_budget_fixed_low": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Fixed Low",
|
||||
"description": "Fixed thinking_budget for budget=low (function='fixed')"
|
||||
},
|
||||
"recall_budget_fixed_mid": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Fixed Mid",
|
||||
"description": "Fixed thinking_budget for budget=mid (function='fixed')"
|
||||
},
|
||||
"recall_budget_fixed_high": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Fixed High",
|
||||
"description": "Fixed thinking_budget for budget=high (function='fixed')"
|
||||
},
|
||||
"recall_budget_adaptive_low": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Adaptive Low",
|
||||
"description": "Ratio of max_tokens for budget=low (function='adaptive')"
|
||||
},
|
||||
"recall_budget_adaptive_mid": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Adaptive Mid",
|
||||
"description": "Ratio of max_tokens for budget=mid (function='adaptive')"
|
||||
},
|
||||
"recall_budget_adaptive_high": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Adaptive High",
|
||||
"description": "Ratio of max_tokens for budget=high (function='adaptive')"
|
||||
},
|
||||
"recall_budget_min": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Min",
|
||||
"description": "Floor for the adaptive function (after clamping)"
|
||||
},
|
||||
"recall_budget_max": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Max",
|
||||
"description": "Ceiling for the adaptive function (after clamping)"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -6546,6 +6974,85 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"EntityGraphResponse": {
|
||||
"properties": {
|
||||
"nodes": {
|
||||
"items": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Nodes"
|
||||
},
|
||||
"edges": {
|
||||
"items": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Edges"
|
||||
},
|
||||
"total_entities": {
|
||||
"type": "integer",
|
||||
"title": "Total Entities"
|
||||
},
|
||||
"total_edges": {
|
||||
"type": "integer",
|
||||
"title": "Total Edges"
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"title": "Limit"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"nodes",
|
||||
"edges",
|
||||
"total_entities",
|
||||
"total_edges",
|
||||
"limit"
|
||||
],
|
||||
"title": "EntityGraphResponse",
|
||||
"description": "Response model for entity co-occurrence graph endpoint.",
|
||||
"example": {
|
||||
"edges": [
|
||||
{
|
||||
"data": {
|
||||
"color": "#ffd700",
|
||||
"id": "uuid-1-uuid-2",
|
||||
"lastCooccurred": "2024-02-01T14:00:00Z",
|
||||
"lineStyle": "solid",
|
||||
"linkType": "cooccurrence",
|
||||
"source": "uuid-1",
|
||||
"target": "uuid-2",
|
||||
"weight": 5
|
||||
}
|
||||
}
|
||||
],
|
||||
"limit": 1000,
|
||||
"nodes": [
|
||||
{
|
||||
"data": {
|
||||
"color": "#42a5f5",
|
||||
"id": "uuid-1",
|
||||
"label": "Alice",
|
||||
"mentionCount": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"color": "#42a5f5",
|
||||
"id": "uuid-2",
|
||||
"label": "Google",
|
||||
"mentionCount": 8
|
||||
}
|
||||
}
|
||||
],
|
||||
"total_edges": 1,
|
||||
"total_entities": 2
|
||||
}
|
||||
},
|
||||
"EntityIncludeOptions": {
|
||||
"properties": {
|
||||
"max_tokens": {
|
||||
@@ -7106,6 +7613,40 @@
|
||||
"total": 25
|
||||
}
|
||||
},
|
||||
"MemoriesTimeseriesResponse": {
|
||||
"properties": {
|
||||
"bank_id": {
|
||||
"type": "string",
|
||||
"title": "Bank Id"
|
||||
},
|
||||
"period": {
|
||||
"type": "string",
|
||||
"title": "Period",
|
||||
"description": "One of: 1h, 12h, 1d, 7d, 30d, 90d."
|
||||
},
|
||||
"trunc": {
|
||||
"type": "string",
|
||||
"title": "Trunc",
|
||||
"description": "Bucket granularity: minute, hour, day."
|
||||
},
|
||||
"buckets": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MemoryTimeseriesBucket"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Buckets",
|
||||
"description": "Per-bucket counts, always returned fully padded for the requested period."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"bank_id",
|
||||
"period",
|
||||
"trunc"
|
||||
],
|
||||
"title": "MemoriesTimeseriesResponse",
|
||||
"description": "Time-series of memory ingestion bucketed by time and fact type."
|
||||
},
|
||||
"MemoryItem": {
|
||||
"properties": {
|
||||
"content": {
|
||||
@@ -7280,6 +7821,39 @@
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
},
|
||||
"MemoryTimeseriesBucket": {
|
||||
"properties": {
|
||||
"time": {
|
||||
"type": "string",
|
||||
"title": "Time",
|
||||
"description": "Bucket start timestamp in ISO-8601 (UTC)."
|
||||
},
|
||||
"world": {
|
||||
"type": "integer",
|
||||
"title": "World",
|
||||
"description": "World-fact memories ingested in this bucket.",
|
||||
"default": 0
|
||||
},
|
||||
"experience": {
|
||||
"type": "integer",
|
||||
"title": "Experience",
|
||||
"description": "Experience memories ingested in this bucket.",
|
||||
"default": 0
|
||||
},
|
||||
"observation": {
|
||||
"type": "integer",
|
||||
"title": "Observation",
|
||||
"description": "Observations recorded in this bucket.",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"time"
|
||||
],
|
||||
"title": "MemoryTimeseriesBucket",
|
||||
"description": "One bucket in the memory ingestion time-series."
|
||||
},
|
||||
"MentalModelListResponse": {
|
||||
"properties": {
|
||||
"items": {
|
||||
@@ -7397,6 +7971,18 @@
|
||||
],
|
||||
"title": "Reflect Response",
|
||||
"description": "Full reflect API response payload including based_on facts and observations"
|
||||
},
|
||||
"is_stale": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Is Stale",
|
||||
"description": "True when new memories matching this mental model's tag/fact_type scope have been ingested since last_refreshed_at, or consolidation has pending items. Only populated when detail=full."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -7502,6 +8088,42 @@
|
||||
],
|
||||
"title": "Tag Groups",
|
||||
"description": "Compound boolean tag expressions to use during refresh instead of the model's own tags. When set, these tag groups are passed to reflect and the model's flat tags are NOT used for filtering. Supports nested and/or/not expressions for complex tag-based scoping."
|
||||
},
|
||||
"include_chunks": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Include Chunks",
|
||||
"description": "Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks)."
|
||||
},
|
||||
"recall_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Max Tokens",
|
||||
"description": "Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens)."
|
||||
},
|
||||
"recall_chunks_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Chunks Max Tokens",
|
||||
"description": "Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens)."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -7602,6 +8224,42 @@
|
||||
],
|
||||
"title": "Tag Groups",
|
||||
"description": "Compound boolean tag expressions to use during refresh instead of the model's own tags. When set, these tag groups are passed to reflect and the model's flat tags are NOT used for filtering. Supports nested and/or/not expressions for complex tag-based scoping."
|
||||
},
|
||||
"include_chunks": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Include Chunks",
|
||||
"description": "Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks)."
|
||||
},
|
||||
"recall_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Max Tokens",
|
||||
"description": "Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens)."
|
||||
},
|
||||
"recall_chunks_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Chunks Max Tokens",
|
||||
"description": "Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens)."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -7770,6 +8428,19 @@
|
||||
],
|
||||
"title": "Child Operations",
|
||||
"description": "Child operations for batch operations (if applicable)"
|
||||
},
|
||||
"task_payload": {
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Task Payload",
|
||||
"description": "Raw task payload (params the operation was submitted with). Only populated when include_payload=true."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
|
||||
@@ -287,6 +287,40 @@ Controls content filtering thresholds for Gemini and VertexAI providers. Accepts
|
||||
|
||||
Only applies when `HINDSIGHT_API_LLM_PROVIDER` is `gemini` or `vertexai`.
|
||||
|
||||
### recall_budget_function {#recall-budget-configuration}
|
||||
|
||||
Selects how the [`recall` request's `budget` parameter](./recall) (`low` / `mid` / `high`) maps to the internal `thinking_budget` integer used by every retrieval method (semantic, BM25, graph, temporal). Two functions are supported:
|
||||
|
||||
| Function | Behaviour |
|
||||
|----------|-----------|
|
||||
| `fixed` *(default)* | `thinking_budget = recall_budget_fixed_<level>` — independent of `max_tokens`. Preserves legacy behavior. |
|
||||
| `adaptive` | `thinking_budget = round(max_tokens * recall_budget_adaptive_<level>)`, clamped to `[recall_budget_min, recall_budget_max]`. Retrieval breadth scales with the requested output size. |
|
||||
|
||||
```json
|
||||
{
|
||||
"recall_budget_function": "adaptive",
|
||||
"recall_budget_adaptive_low": 0.05,
|
||||
"recall_budget_adaptive_mid": 0.1,
|
||||
"recall_budget_adaptive_high": 0.3,
|
||||
"recall_budget_min": 30,
|
||||
"recall_budget_max": 1500
|
||||
}
|
||||
```
|
||||
|
||||
### recall_budget_fixed_low / recall_budget_fixed_mid / recall_budget_fixed_high
|
||||
|
||||
When `recall_budget_function` is `fixed` (the default), these positive integers are used directly as the per-method retrieval limit for each `budget` level. Defaults: `100` / `300` / `1000` — exactly matching the legacy hardcoded mapping.
|
||||
|
||||
### recall_budget_adaptive_low / recall_budget_adaptive_mid / recall_budget_adaptive_high
|
||||
|
||||
When `recall_budget_function` is `adaptive`, these positive ratios multiply the request's `max_tokens` to derive the per-method retrieval limit. Defaults: `0.025` / `0.075` / `0.25` — chosen to roughly match the fixed defaults at `max_tokens = 4096`.
|
||||
|
||||
### recall_budget_min / recall_budget_max
|
||||
|
||||
Floor and ceiling applied to the result of the adaptive function (after the ratio multiplication). Both must be positive integers and `min ≤ max`. Defaults: `20` / `2000`.
|
||||
|
||||
See [Recall budget mapping](../configuration.md#recall-budget-mapping) for environment variable names and full defaults.
|
||||
|
||||
---
|
||||
|
||||
## Updating Configuration
|
||||
|
||||
@@ -685,6 +685,27 @@ For advanced authentication (JWT, OAuth, multi-tenant schemas), implement a cust
|
||||
|
||||
- **`link_expansion`** (default): Fast graph expansion from semantic seeds via entity co-occurrence, semantic kNN, and causal links. Target latency under 100ms.
|
||||
|
||||
#### Recall budget mapping
|
||||
|
||||
The recall request takes a `budget` parameter (`low` / `mid` / `high`, default `mid`) that maps to an integer `thinking_budget` used by every retrieval method (semantic, BM25, graph, temporal). These knobs control that mapping. They are hierarchical — overridable per bank via the [config API](#hierarchical-configuration).
|
||||
|
||||
Two functions are available:
|
||||
|
||||
- **`fixed`** (default — preserves legacy behavior): `thinking_budget = recall_budget_fixed_<level>` (independent of `max_tokens`).
|
||||
- **`adaptive`**: `thinking_budget = round(max_tokens * recall_budget_adaptive_<level>)`, clamped to `[recall_budget_min, recall_budget_max]`. Useful when callers vary `max_tokens` and you want retrieval breadth to scale with the requested output size.
|
||||
|
||||
| Variable | Description | Default |
|
||||
|----------|-------------|---------|
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FUNCTION` | Mapping function: `fixed` or `adaptive`. | `fixed` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FIXED_LOW` | Items per retrieval method per fact type when `budget=low` and function is `fixed`. | `100` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FIXED_MID` | Items per retrieval method per fact type when `budget=mid` and function is `fixed`. | `300` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_FIXED_HIGH` | Items per retrieval method per fact type when `budget=high` and function is `fixed`. | `1000` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_LOW` | Ratio of request `max_tokens` used when `budget=low` and function is `adaptive`. | `0.025` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_MID` | Ratio of request `max_tokens` used when `budget=mid` and function is `adaptive`. | `0.075` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_ADAPTIVE_HIGH` | Ratio of request `max_tokens` used when `budget=high` and function is `adaptive`. | `0.25` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_MIN` | Floor for the adaptive function (after clamping). | `20` |
|
||||
| `HINDSIGHT_API_RECALL_BUDGET_MAX` | Ceiling for the adaptive function (after clamping). | `2000` |
|
||||
|
||||
### Retain
|
||||
|
||||
Controls the retain (memory ingestion) pipeline.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"name": "Apache 2.0",
|
||||
"url": "https://www.apache.org/licenses/LICENSE-2.0.html"
|
||||
},
|
||||
"version": "0.5.0"
|
||||
"version": "0.5.2"
|
||||
},
|
||||
"paths": {
|
||||
"/health": {
|
||||
@@ -255,6 +255,22 @@
|
||||
"title": "Q"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "consolidation_state",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation State"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
@@ -695,6 +711,75 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/stats/memories-timeseries": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Banks"
|
||||
],
|
||||
"summary": "Memory ingestion time-series",
|
||||
"description": "Memories ingested over a period, bucketed by time and broken down by fact type.",
|
||||
"operationId": "get_memories_timeseries",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bank_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Bank Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "period",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"default": "7d",
|
||||
"title": "Period"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "authorization",
|
||||
"in": "header",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/MemoriesTimeseriesResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/entities": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -778,6 +863,89 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/entities/graph": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Entities"
|
||||
],
|
||||
"summary": "Get entity co-occurrence graph",
|
||||
"description": "Return a graph of entities (nodes) and their co-occurrences (edges) for visualization.",
|
||||
"operationId": "get_entity_graph",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "bank_id",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Bank Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"description": "Maximum number of co-occurrence edges to return",
|
||||
"default": 1000,
|
||||
"title": "Limit"
|
||||
},
|
||||
"description": "Maximum number of co-occurrence edges to return"
|
||||
},
|
||||
{
|
||||
"name": "min_count",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"description": "Minimum cooccurrence_count to include an edge",
|
||||
"default": 1,
|
||||
"title": "Min Count"
|
||||
},
|
||||
"description": "Minimum cooccurrence_count to include an edge"
|
||||
},
|
||||
{
|
||||
"name": "authorization",
|
||||
"in": "header",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Authorization"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/EntityGraphResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/v1/default/banks/{bank_id}/entities/{entity_id}": {
|
||||
"get": {
|
||||
"tags": [
|
||||
@@ -2534,6 +2702,18 @@
|
||||
"title": "Operation Id"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "include_payload",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"type": "boolean",
|
||||
"description": "Include the raw task payload (submission params) in the response. May be large.",
|
||||
"default": false,
|
||||
"title": "Include Payload"
|
||||
},
|
||||
"description": "Include the raw task payload (submission params) in the response. May be large."
|
||||
},
|
||||
{
|
||||
"name": "authorization",
|
||||
"in": "header",
|
||||
@@ -5069,6 +5249,14 @@
|
||||
"type": "integer",
|
||||
"title": "Failed Operations"
|
||||
},
|
||||
"operations_by_status": {
|
||||
"additionalProperties": {
|
||||
"type": "integer"
|
||||
},
|
||||
"type": "object",
|
||||
"title": "Operations By Status",
|
||||
"description": "Async operations grouped by status (pending, in_progress, completed, failed, cancelled)."
|
||||
},
|
||||
"last_consolidated_at": {
|
||||
"anyOf": [
|
||||
{
|
||||
@@ -5087,6 +5275,12 @@
|
||||
"description": "Number of memories not yet processed into observations",
|
||||
"default": 0
|
||||
},
|
||||
"failed_consolidation": {
|
||||
"type": "integer",
|
||||
"title": "Failed Consolidation",
|
||||
"description": "Number of source memories (world/experience) whose consolidation permanently failed and can be retried via the consolidation recovery endpoint.",
|
||||
"default": 0
|
||||
},
|
||||
"total_observations": {
|
||||
"type": "integer",
|
||||
"title": "Total Observations",
|
||||
@@ -5111,6 +5305,7 @@
|
||||
"description": "Response model for bank statistics endpoint.",
|
||||
"example": {
|
||||
"bank_id": "user123",
|
||||
"failed_consolidation": 0,
|
||||
"failed_operations": 0,
|
||||
"last_consolidated_at": "2024-01-15T10:30:00Z",
|
||||
"links_breakdown": {
|
||||
@@ -5298,6 +5493,239 @@
|
||||
],
|
||||
"title": "Entities Allow Free Form",
|
||||
"description": "Allow entities outside the label vocabulary"
|
||||
},
|
||||
"retain_default_strategy": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Retain Default Strategy",
|
||||
"description": "Name of the default retain strategy (key into retain_strategies map)"
|
||||
},
|
||||
"retain_strategies": {
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Retain Strategies",
|
||||
"description": "Map of retain strategy name to per-strategy config dict"
|
||||
},
|
||||
"retain_chunk_batch_size": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Retain Chunk Batch Size",
|
||||
"description": "Max chunks per streaming batch (0 disables batching)"
|
||||
},
|
||||
"mcp_enabled_tools": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Mcp Enabled Tools",
|
||||
"description": "MCP tool allowlist for this bank (None = all tools)"
|
||||
},
|
||||
"consolidation_llm_batch_size": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation Llm Batch Size",
|
||||
"description": "LLM batch size for observation consolidation"
|
||||
},
|
||||
"consolidation_source_facts_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation Source Facts Max Tokens",
|
||||
"description": "Max tokens of source facts per consolidation batch"
|
||||
},
|
||||
"consolidation_source_facts_max_tokens_per_observation": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Consolidation Source Facts Max Tokens Per Observation",
|
||||
"description": "Max tokens of source facts per observation"
|
||||
},
|
||||
"max_observations_per_scope": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Max Observations Per Scope",
|
||||
"description": "Max observations to retain per consolidation scope"
|
||||
},
|
||||
"reflect_source_facts_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Reflect Source Facts Max Tokens",
|
||||
"description": "Max tokens of source facts per reflect call"
|
||||
},
|
||||
"llm_gemini_safety_settings": {
|
||||
"anyOf": [
|
||||
{
|
||||
"items": {},
|
||||
"type": "array"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Llm Gemini Safety Settings",
|
||||
"description": "Per-bank Gemini/VertexAI safety filter settings"
|
||||
},
|
||||
"recall_budget_function": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Function",
|
||||
"description": "Recall budget mapping function: 'fixed' or 'adaptive'"
|
||||
},
|
||||
"recall_budget_fixed_low": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Fixed Low",
|
||||
"description": "Fixed thinking_budget for budget=low (function='fixed')"
|
||||
},
|
||||
"recall_budget_fixed_mid": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Fixed Mid",
|
||||
"description": "Fixed thinking_budget for budget=mid (function='fixed')"
|
||||
},
|
||||
"recall_budget_fixed_high": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Fixed High",
|
||||
"description": "Fixed thinking_budget for budget=high (function='fixed')"
|
||||
},
|
||||
"recall_budget_adaptive_low": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Adaptive Low",
|
||||
"description": "Ratio of max_tokens for budget=low (function='adaptive')"
|
||||
},
|
||||
"recall_budget_adaptive_mid": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Adaptive Mid",
|
||||
"description": "Ratio of max_tokens for budget=mid (function='adaptive')"
|
||||
},
|
||||
"recall_budget_adaptive_high": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Adaptive High",
|
||||
"description": "Ratio of max_tokens for budget=high (function='adaptive')"
|
||||
},
|
||||
"recall_budget_min": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Min",
|
||||
"description": "Floor for the adaptive function (after clamping)"
|
||||
},
|
||||
"recall_budget_max": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Budget Max",
|
||||
"description": "Ceiling for the adaptive function (after clamping)"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -6546,6 +6974,85 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"EntityGraphResponse": {
|
||||
"properties": {
|
||||
"nodes": {
|
||||
"items": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Nodes"
|
||||
},
|
||||
"edges": {
|
||||
"items": {
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Edges"
|
||||
},
|
||||
"total_entities": {
|
||||
"type": "integer",
|
||||
"title": "Total Entities"
|
||||
},
|
||||
"total_edges": {
|
||||
"type": "integer",
|
||||
"title": "Total Edges"
|
||||
},
|
||||
"limit": {
|
||||
"type": "integer",
|
||||
"title": "Limit"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"nodes",
|
||||
"edges",
|
||||
"total_entities",
|
||||
"total_edges",
|
||||
"limit"
|
||||
],
|
||||
"title": "EntityGraphResponse",
|
||||
"description": "Response model for entity co-occurrence graph endpoint.",
|
||||
"example": {
|
||||
"edges": [
|
||||
{
|
||||
"data": {
|
||||
"color": "#ffd700",
|
||||
"id": "uuid-1-uuid-2",
|
||||
"lastCooccurred": "2024-02-01T14:00:00Z",
|
||||
"lineStyle": "solid",
|
||||
"linkType": "cooccurrence",
|
||||
"source": "uuid-1",
|
||||
"target": "uuid-2",
|
||||
"weight": 5
|
||||
}
|
||||
}
|
||||
],
|
||||
"limit": 1000,
|
||||
"nodes": [
|
||||
{
|
||||
"data": {
|
||||
"color": "#42a5f5",
|
||||
"id": "uuid-1",
|
||||
"label": "Alice",
|
||||
"mentionCount": 12
|
||||
}
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"color": "#42a5f5",
|
||||
"id": "uuid-2",
|
||||
"label": "Google",
|
||||
"mentionCount": 8
|
||||
}
|
||||
}
|
||||
],
|
||||
"total_edges": 1,
|
||||
"total_entities": 2
|
||||
}
|
||||
},
|
||||
"EntityIncludeOptions": {
|
||||
"properties": {
|
||||
"max_tokens": {
|
||||
@@ -7106,6 +7613,40 @@
|
||||
"total": 25
|
||||
}
|
||||
},
|
||||
"MemoriesTimeseriesResponse": {
|
||||
"properties": {
|
||||
"bank_id": {
|
||||
"type": "string",
|
||||
"title": "Bank Id"
|
||||
},
|
||||
"period": {
|
||||
"type": "string",
|
||||
"title": "Period",
|
||||
"description": "One of: 1h, 12h, 1d, 7d, 30d, 90d."
|
||||
},
|
||||
"trunc": {
|
||||
"type": "string",
|
||||
"title": "Trunc",
|
||||
"description": "Bucket granularity: minute, hour, day."
|
||||
},
|
||||
"buckets": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/MemoryTimeseriesBucket"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Buckets",
|
||||
"description": "Per-bucket counts, always returned fully padded for the requested period."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"bank_id",
|
||||
"period",
|
||||
"trunc"
|
||||
],
|
||||
"title": "MemoriesTimeseriesResponse",
|
||||
"description": "Time-series of memory ingestion bucketed by time and fact type."
|
||||
},
|
||||
"MemoryItem": {
|
||||
"properties": {
|
||||
"content": {
|
||||
@@ -7280,6 +7821,39 @@
|
||||
"timestamp": "2024-01-15T10:30:00Z"
|
||||
}
|
||||
},
|
||||
"MemoryTimeseriesBucket": {
|
||||
"properties": {
|
||||
"time": {
|
||||
"type": "string",
|
||||
"title": "Time",
|
||||
"description": "Bucket start timestamp in ISO-8601 (UTC)."
|
||||
},
|
||||
"world": {
|
||||
"type": "integer",
|
||||
"title": "World",
|
||||
"description": "World-fact memories ingested in this bucket.",
|
||||
"default": 0
|
||||
},
|
||||
"experience": {
|
||||
"type": "integer",
|
||||
"title": "Experience",
|
||||
"description": "Experience memories ingested in this bucket.",
|
||||
"default": 0
|
||||
},
|
||||
"observation": {
|
||||
"type": "integer",
|
||||
"title": "Observation",
|
||||
"description": "Observations recorded in this bucket.",
|
||||
"default": 0
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"time"
|
||||
],
|
||||
"title": "MemoryTimeseriesBucket",
|
||||
"description": "One bucket in the memory ingestion time-series."
|
||||
},
|
||||
"MentalModelListResponse": {
|
||||
"properties": {
|
||||
"items": {
|
||||
@@ -7397,6 +7971,18 @@
|
||||
],
|
||||
"title": "Reflect Response",
|
||||
"description": "Full reflect API response payload including based_on facts and observations"
|
||||
},
|
||||
"is_stale": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Is Stale",
|
||||
"description": "True when new memories matching this mental model's tag/fact_type scope have been ingested since last_refreshed_at, or consolidation has pending items. Only populated when detail=full."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -7502,6 +8088,42 @@
|
||||
],
|
||||
"title": "Tag Groups",
|
||||
"description": "Compound boolean tag expressions to use during refresh instead of the model's own tags. When set, these tag groups are passed to reflect and the model's flat tags are NOT used for filtering. Supports nested and/or/not expressions for complex tag-based scoping."
|
||||
},
|
||||
"include_chunks": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Include Chunks",
|
||||
"description": "Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks)."
|
||||
},
|
||||
"recall_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Max Tokens",
|
||||
"description": "Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens)."
|
||||
},
|
||||
"recall_chunks_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Chunks Max Tokens",
|
||||
"description": "Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens)."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -7602,6 +8224,42 @@
|
||||
],
|
||||
"title": "Tag Groups",
|
||||
"description": "Compound boolean tag expressions to use during refresh instead of the model's own tags. When set, these tag groups are passed to reflect and the model's flat tags are NOT used for filtering. Supports nested and/or/not expressions for complex tag-based scoping."
|
||||
},
|
||||
"include_chunks": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "boolean"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Include Chunks",
|
||||
"description": "Override whether the internal recall used during refresh returns raw chunk text. None means use the bank/global config default (recall_include_chunks)."
|
||||
},
|
||||
"recall_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Max Tokens",
|
||||
"description": "Override the token budget for facts returned by the internal recall during refresh. None means use the bank/global config default (recall_max_tokens)."
|
||||
},
|
||||
"recall_chunks_max_tokens": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "integer"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Recall Chunks Max Tokens",
|
||||
"description": "Override the token budget for raw chunks returned by the internal recall during refresh. None means use the bank/global config default (recall_chunks_max_tokens)."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
@@ -7770,6 +8428,19 @@
|
||||
],
|
||||
"title": "Child Operations",
|
||||
"description": "Child operations for batch operations (if applicable)"
|
||||
},
|
||||
"task_payload": {
|
||||
"anyOf": [
|
||||
{
|
||||
"additionalProperties": true,
|
||||
"type": "object"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Task Payload",
|
||||
"description": "Raw task payload (params the operation was submitted with). Only populated when include_payload=true."
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
|
||||
Reference in New Issue
Block a user