* feat: introduce hindsight-api-slim and hindsight-all-slim packages Closes #552 - Move all source code from hindsight-api/ to new hindsight-api-slim/ - hindsight-api-slim has heavy ML deps (torch, sentence-transformers, transformers, einops, flashrank, mlx, mlx-lm, safetensors) and pg0-embedded as optional extras: [local-ml], [embedded-db], [all] - hindsight-api becomes a zero-code meta-package depending on hindsight-api-slim[all] for full backward compatibility - Add hindsight-all-slim meta-package: hindsight-api-slim + client + embed - hindsight-all updated to depend on hindsight-api-slim[all] - pg0.py: lazy-import pg0 with clear ImportError pointing to [embedded-db] - Dockerfile: replace sed hack with proper uv sync --extra flags - Update release.yml, test.yml, lint.sh, release.sh, CLAUDE.md and all path references throughout the repo * refactor: rename hindsight/ directory to hindsight-all/ * docs: document hindsight-api-slim and hindsight-all-slim package variants Add package variants table and extras explanation to installation.md * docs: remove emojis from installation.md, use professional tone * docs: link Docker slim variant to pip package variants section * docs: consolidate Docker image variants into single table * ci: fix working-directory paths after package restructure - Replace all hindsight-api → hindsight-api-slim in test.yml - Replace hindsight → hindsight-all in test.yml - Add --extra embedded-db to test-embed API install step * ci: add local-ml and embedded-db extras to API sync steps These extras were previously implicit in the old hindsight-api package (which bundled everything). Now that hindsight-api-slim uses optional extras, we must explicitly request local-ml and embedded-db in CI. * ci: add API install step with embedded-db to test-embed smoke test The smoke test starts hindsight-api as a daemon, which requires pg0-embedded. Add a dedicated install step for hindsight-api-slim with embedded-db extra so the daemon can start successfully. * ci: remove --no-install-project when using optional extras When --no-install-project is combined with --extra, the optional deps are not installed because extras require the project to be active. Remove --no-install-project from steps that need local-ml or embedded-db. * ci: fix ordering of uv sync steps to preserve optional extras When uv sync runs for a different workspace member, it removes optional extras installed for other members. Fix by always running extra-requiring API sync last, after other workspace member syncs. Also remove --no-install-project from embedded-db sync in test-embed, as --no-install-project prevents optional extras from being active. * ci: add local-ml extra to test-embed API install for smoke test The smoke test starts the full API server which needs sentence-transformers for local embeddings (default provider). Add local-ml extra to the install. * ci: simplify extras with --all-extras and add slim pip smoke test - Replace explicit --extra local-ml --extra embedded-db with --all-extras for cleaner, more maintainable sync steps - Add test-pip-slim job: tests hindsight-api-slim[embedded-db] without local ML models, using Cohere for embeddings/reranking (mirrors Docker slim smoke test approach) * ci: simplify slim smoke test to health check only (mirrors Docker test)
259 lines
11 KiB
Python
259 lines
11 KiB
Python
"""
|
|
Tool schema definitions for the reflect agent.
|
|
|
|
These are OpenAI-format tool definitions used with native tool calling.
|
|
The reflect agent uses a hierarchical retrieval strategy:
|
|
1. search_mental_models - User-curated stored reflect responses (highest quality, if applicable)
|
|
2. search_observations - Consolidated knowledge with freshness awareness
|
|
3. recall - Raw facts (world/experience) as ground truth fallback
|
|
"""
|
|
|
|
# Tool definitions in OpenAI format
|
|
|
|
TOOL_SEARCH_MENTAL_MODELS = {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "search_mental_models",
|
|
"description": (
|
|
"Search user-curated mental models (stored reflect responses). These are high-quality, manually created "
|
|
"summaries about specific topics. Use FIRST when the question might be covered by an "
|
|
"existing mental model. Returns mental models with their content and last refresh time."
|
|
),
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"reason": {
|
|
"type": "string",
|
|
"description": "Brief explanation of why you're making this search (for debugging)",
|
|
},
|
|
"query": {
|
|
"type": "string",
|
|
"description": "Search query to find relevant mental models",
|
|
},
|
|
"max_results": {
|
|
"type": "integer",
|
|
"description": "Maximum number of mental models to return (default 5)",
|
|
},
|
|
},
|
|
"required": ["reason", "query"],
|
|
},
|
|
},
|
|
}
|
|
|
|
TOOL_SEARCH_OBSERVATIONS = {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "search_observations",
|
|
"description": (
|
|
"Search consolidated observations (auto-generated knowledge). These are automatically "
|
|
"synthesized from memories. Returns observations with freshness info (updated_at, is_stale). "
|
|
"If an observation is STALE, you should ALSO use recall() to verify with current facts. "
|
|
"IMPORTANT: If search_mental_models is available, you MUST call it FIRST before using this tool."
|
|
),
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"reason": {
|
|
"type": "string",
|
|
"description": "Brief explanation of why you're making this search (for debugging)",
|
|
},
|
|
"query": {
|
|
"type": "string",
|
|
"description": "Search query to find relevant observations",
|
|
},
|
|
"max_tokens": {
|
|
"type": "integer",
|
|
"description": "Maximum tokens for results (default 5000). Use higher values for broader searches.",
|
|
},
|
|
},
|
|
"required": ["reason", "query"],
|
|
},
|
|
},
|
|
}
|
|
|
|
TOOL_RECALL = {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "recall",
|
|
"description": (
|
|
"Search raw memories (facts and experiences). This is the ground truth data. "
|
|
"Use when: (1) no reflections/mental models exist, (2) mental models are stale, "
|
|
"(3) you need specific details not in synthesized knowledge. "
|
|
"Returns individual memory facts with their timestamps."
|
|
),
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"reason": {
|
|
"type": "string",
|
|
"description": "Brief explanation of why you're making this search (for debugging)",
|
|
},
|
|
"query": {
|
|
"type": "string",
|
|
"description": "Search query string",
|
|
},
|
|
"max_tokens": {
|
|
"type": "integer",
|
|
"description": "Optional limit on result size (default 2048). Use higher values for broader searches.",
|
|
},
|
|
"max_chunk_tokens": {
|
|
"type": "integer",
|
|
"description": "Maximum tokens for raw source chunk text included alongside each memory fact (default 1000, min 1000). Chunks provide the surrounding context the fact was extracted from. Increase for broader context.",
|
|
},
|
|
},
|
|
"required": ["reason", "query"],
|
|
},
|
|
},
|
|
}
|
|
|
|
TOOL_EXPAND = {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "expand",
|
|
"description": "Get more context for one or more memories. Memory hierarchy: memory -> chunk -> document.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"reason": {
|
|
"type": "string",
|
|
"description": "Brief explanation of why you need more context (for debugging)",
|
|
},
|
|
"memory_ids": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
"description": "Array of memory IDs from recall results (batch multiple for efficiency)",
|
|
},
|
|
"depth": {
|
|
"type": "string",
|
|
"enum": ["chunk", "document"],
|
|
"description": "chunk: surrounding text chunk, document: full source document",
|
|
},
|
|
},
|
|
"required": ["reason", "memory_ids", "depth"],
|
|
},
|
|
},
|
|
}
|
|
|
|
TOOL_DONE_ANSWER = {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "done",
|
|
"description": "Signal completion with your final answer. Use this when you have gathered enough information to answer the question.",
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"answer": {
|
|
"type": "string",
|
|
"description": "Your response as well-formatted markdown. Use headers, lists, bold/italic, and code blocks for clarity. NEVER include memory IDs, UUIDs, or 'Memory references' in this text - put IDs only in memory_ids array. LANGUAGE: By default, write in the SAME language as the user's question. However, if a language directive in the system prompt specifies a different language, follow that directive instead.",
|
|
},
|
|
"memory_ids": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
"description": "Array of memory IDs that support your answer (put IDs here, NOT in answer text)",
|
|
},
|
|
"mental_model_ids": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
"description": "Array of mental model IDs that support your answer",
|
|
},
|
|
"observation_ids": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
"description": "Array of observation IDs that support your answer",
|
|
},
|
|
},
|
|
"required": ["answer"],
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def _build_done_tool_with_directives(directive_rules: list[str]) -> dict:
|
|
"""
|
|
Build the done tool schema with directive compliance field.
|
|
|
|
When directives are present, adds a required field that forces the agent
|
|
to confirm compliance with each directive before submitting.
|
|
|
|
Args:
|
|
directive_rules: List of directive rule strings
|
|
"""
|
|
# Build rules list for description
|
|
rules_list = "\n".join(f" {i + 1}. {rule}" for i, rule in enumerate(directive_rules))
|
|
|
|
# Build the tool with directive compliance field
|
|
return {
|
|
"type": "function",
|
|
"function": {
|
|
"name": "done",
|
|
"description": (
|
|
"Signal completion with your final answer. IMPORTANT: You must confirm directive compliance before submitting. "
|
|
"Your answer will be REJECTED if it violates any directive."
|
|
),
|
|
"parameters": {
|
|
"type": "object",
|
|
"properties": {
|
|
"answer": {
|
|
"type": "string",
|
|
"description": (
|
|
"Your response as well-formatted markdown. Use headers, lists, bold/italic, and code blocks for clarity. "
|
|
"NEVER include memory IDs, UUIDs, or 'Memory references' in this text - put IDs only in memory_ids array. "
|
|
f"MANDATORY: Your answer MUST comply with ALL directives:\n{rules_list}"
|
|
),
|
|
},
|
|
"memory_ids": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
"description": "Array of memory IDs that support your answer (put IDs here, NOT in answer text)",
|
|
},
|
|
"mental_model_ids": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
"description": "Array of mental model IDs that support your answer",
|
|
},
|
|
"observation_ids": {
|
|
"type": "array",
|
|
"items": {"type": "string"},
|
|
"description": "Array of observation IDs that support your answer",
|
|
},
|
|
"directive_compliance": {
|
|
"type": "string",
|
|
"description": f"REQUIRED: Confirm your answer complies with ALL directives. List each directive and how your answer follows it:\n{rules_list}\n\nFormat: 'Directive 1: [how answer complies]. Directive 2: [how answer complies]...'",
|
|
},
|
|
},
|
|
"required": ["answer", "directive_compliance"],
|
|
},
|
|
},
|
|
}
|
|
|
|
|
|
def get_reflect_tools(directive_rules: list[str] | None = None) -> list[dict]:
|
|
"""
|
|
Get the list of tools for the reflect agent.
|
|
|
|
The tools support a hierarchical retrieval strategy:
|
|
1. search_mental_models - User-curated stored reflect responses (try first)
|
|
2. search_observations - Consolidated knowledge with freshness
|
|
3. recall - Raw facts as ground truth
|
|
|
|
Args:
|
|
directive_rules: Optional list of directive rule strings. If provided,
|
|
the done() tool will require directive compliance confirmation.
|
|
|
|
Returns:
|
|
List of tool definitions in OpenAI format
|
|
"""
|
|
tools = [
|
|
TOOL_SEARCH_MENTAL_MODELS,
|
|
TOOL_SEARCH_OBSERVATIONS,
|
|
TOOL_RECALL,
|
|
TOOL_EXPAND,
|
|
]
|
|
|
|
# Use directive-aware done tool if directives are present
|
|
if directive_rules:
|
|
tools.append(_build_done_tool_with_directives(directive_rules))
|
|
else:
|
|
tools.append(TOOL_DONE_ANSWER)
|
|
|
|
return tools
|