"""
Context-aware LLM prompting system.
This module provides the prompt templates and generation logic for
context-aware LLM interactions.
"""
from __future__ import annotations
from typing import Any, Dict, List
from src.core.context_router import ContextRouter
from src.core.tool_context import PageContext, EntityType
from src.observability import get_logger
logger = get_logger(__name__)
# Base system prompt template
SYSTEM_PROMPT = """You are an AI assistant helping users with the Updation vendor management system.
{context_section}
IMPORTANT RULES:
1. You can ONLY use tools that are explicitly provided to you
2. NEVER assume or guess entity IDs - they must be provided by the context
3. If a tool isn't available, explain why and how to navigate to use it
4. ALWAYS check context before suggesting actions
5. NEVER try to access data outside your current context
6. If you need an entity ID, ask the user to select/navigate to that entity
Your responses should be:
- Clear and concise
- Focused on the current context
- Explicit about navigation needs
- Honest about limitations
"""
# Context section template
CONTEXT_SECTION = """CURRENT CONTEXT:
- Page: {page_type}
- Entity Type: {entity_type}
- Entity ID: {entity_id}
AVAILABLE TOOLS:
{tool_list}
ALLOWED ACTIONS:
{allowed_actions}"""
def generate_system_prompt(
context_router: ContextRouter,
available_tools: List[Dict[str, Any]]
) -> str:
"""
Generate the system prompt with current context.
Args:
context_router: Current context router
available_tools: List of available tools
Returns:
Complete system prompt with context
"""
context = context_router.current_context
if not context:
context = PageContext(
page_type="unknown",
entity_type=None,
entity_id=None
)
# Get context summary
summary = context_router.get_context_summary()
# Build tool list
tool_list = "\n".join(f"- {t['name']}: {t['description']}"
for t in available_tools)
# Determine allowed actions
allowed_actions = []
if context.page_type.endswith("_TABLE"):
allowed_actions.append("- List and filter items")
allowed_actions.append("- Export data")
allowed_actions.append("- Perform bulk actions")
elif context.page_type.endswith("_DETAIL"):
allowed_actions.append("- View detailed information")
allowed_actions.append("- Update entity details")
allowed_actions.append("- View related entities")
elif context.page_type.endswith("_CREATE"):
allowed_actions.append("- Create new entities")
allowed_actions.append("- Upload documents")
# Format context section
context_section = CONTEXT_SECTION.format(
page_type=summary["page_type"],
entity_type=summary["entity_type"],
entity_id=summary["entity_id"],
tool_list=tool_list,
allowed_actions="\n".join(allowed_actions)
)
# Generate full prompt
return SYSTEM_PROMPT.format(context_section=context_section)
def generate_tool_error_message(
context_router: ContextRouter,
requested_tool: str
) -> str:
"""
Generate an error message when a tool can't be used.
Args:
context_router: Current context router
requested_tool: Name of requested tool
Returns:
User-friendly error message with navigation hints
"""
hint = context_router.get_navigation_hints(requested_tool)
if hint:
return f"I cannot use that tool right now. {hint}"
return (
"I cannot use that tool right now. "
"It may not be available or you may need different permissions."
)
# Developer prompt template
DEVELOPER_PROMPT = """CONTEXT-AWARE TOOL DEVELOPMENT
When creating new tools:
1. ALWAYS declare a ToolContextPolicy with:
- allowed_page_types: Set of pages where tool can run
- requires_entity: Whether tool needs an entity in focus
- entity_type: Type of entity required (if any)
- read_only: Whether tool modifies data
2. NEVER assume context:
- Get page type from context
- Get entity ID from context
- Check policy requirements
3. Use the ContextAwareToolRegistry:
- Register with @registry.register_tool
- Provide complete policy
- Include clear description
4. Follow best practices:
- One tool = one clear purpose
- Validate all inputs
- Return structured data
- Use proper error handling
- Add logging
Example:
```python
@registry.register_tool(
name="get_vendor_details",
policy=ToolContextPolicy(
allowed_page_types={PageType.VENDOR_DETAIL},
requires_entity=True,
entity_type=EntityType.VENDOR,
read_only=True
),
description="Get detailed information about a vendor"
)
async def get_vendor_details(
vendor_id: str,
user_context: UserContext
) -> Dict[str, Any]:
# Implementation
pass
```
"""