---------------------------------------------------------------------- This is the API documentation for the talk_box library. ---------------------------------------------------------------------- ## Getting Started Core classes for building AI assistants ChatBot(name: Optional[str] = None, description: Optional[str] = None, id: Optional[str] = None) -> None Main entry point for building and managing conversational AI chatbots with integrated conversation handling. The `ChatBot` class is the primary interface for creating intelligent chatbots in Talk Box. It provides a chainable API for configuration and returns `Conversation` objects that manage message history and context. This design creates a natural learning path where users start with `ChatBot` for configuration, receive `Conversation` objects for message management, and discover `Message` objects within conversations. **Layered API Design**: 1. **ChatBot** (this class): configuration and interaction entry point 2. **Conversation**: multi-turn conversation management and message history 3. **Message**: individual message data structures with metadata The integration ensures that all chat interactions automatically create and manage conversation history, making multi-turn conversations natural and persistent. Advanced users can access lower-level `Conversation` and `Message` classes for specialized use cases. Notes ----- The `ChatBot` class takes no initialization parameters. All configuration is done through the chainable methods after instantiation. Returns ------- ChatBot A new `ChatBot` instance with default configuration and auto-enabled LLM integration (when available). Conversation Management ---------------------- All chat interactions return `Conversation` objects, providing seamless conversation management: - [`chat()`](`talk_box.ChatBot.chat`): send message and get conversation with response - [`start_conversation()`](`talk_box.ChatBot.start_conversation`): create new empty conversation - [`continue_conversation()`](`talk_box.ChatBot.continue_conversation`): continue existing conversation Conversations automatically handle message history, chronological ordering, and context management. Users can access individual `Message` objects within conversations for detailed inspection. Chainable Configuration Methods ------------------------------ Configure your chatbot behavior with these chainable methods: - [`model()`](`talk_box.ChatBot.model`): set the language model to use - [`preset()`](`talk_box.ChatBot.preset`): apply behavior presets like `"technical_advisor"` - [`temperature()`](`talk_box.ChatBot.temperature`): control response randomness (`0.0`-`2.0`) - [`max_tokens()`](`talk_box.ChatBot.max_tokens`): set maximum response length - [`tools()`](`talk_box.ChatBot.tools`): enable specific tools and capabilities - [`persona()`](`talk_box.ChatBot.persona`): define the chatbot's personality - [`avoid()`](`talk_box.ChatBot.avoid`): specify topics or behaviors to avoid - [`verbose()`](`talk_box.ChatBot.verbose`): enable detailed output logging All configuration methods return `self`, enabling method chaining for concise setup. Browser Integration ------------------ The `ChatBot` class provides interactive browser interfaces: - **Automatic Launch**: when displayed in Jupyter notebooks, opens browser chat interface - **Manual Sessions**: use [`create_chat_session()`](`talk_box.ChatBot.create_chat_session`) for explicit browser interface control - **Configuration Display**: shows current configuration when LLM integration unavailable Examples -------- ### Basic conversation flow The natural progression from ChatBot to Conversation to Message: ```python import talk_box as tb # 1. Configure chatbot (entry point) bot = tb.ChatBot().model("gpt-4").temperature(0.7).preset("helpful") # 2. Start conversation (returns Conversation object) conversation = bot.chat("Hello! What can you help me with?") # 3. Continue conversation (updates Conversation) conversation = bot.chat("Tell me about machine learning", conversation=conversation) # 4. Access individual messages (Message objects) for message in conversation.get_messages(): print(f"{message.role}: {message.content}") print(f"Timestamp: {message.timestamp}") ``` ### Advanced conversation management Explicit conversation management for complex workflows: ```python # Start with empty conversation conversation = bot.start_conversation() # Add multiple exchanges conversation = bot.continue_conversation(conversation, "What's the weather?") conversation = bot.continue_conversation(conversation, "What about tomorrow?") # Access conversation metadata print(f"Total messages: {conversation.get_message_count()}") print(f"Last message: {conversation.get_last_message().content}") # Filter by role user_messages = conversation.get_messages(role="user") assistant_messages = conversation.get_messages(role="assistant") ``` ### Discovering the full API layer by layer Start simple and naturally discover more advanced features: ```python import talk_box as tb # Layer 1: Basic ChatBot usage bot = tb.ChatBot().model("gpt-4") convo = bot.chat("Hello!") # Layer 2: Conversation management (discovered from return type) convo.add_user_message("Another question") messages = convo.get_messages() # Layer 3: Message details (discovered from conversation contents) latest = convo.get_last_message() print(f"Message ID: {latest.message_id}") print(f"Metadata: {latest.metadata}") # Layer 4: Advanced conversation features convo.set_context_window(10) # Limit conversation length context_msgs = convo.get_context_messages() # Get messages in context window ``` Conversation(conversation_id: Optional[str] = None) -> None Manages sequences of messages in conversational AI interactions, primarily returned by ChatBot methods. The `Conversation` class is automatically created and returned by `ChatBot` chat methods, serving as the primary container for managing multi-turn conversations between users and AI assistants. This integration with `ChatBot` creates a natural progression where users start with chatbot configuration and receive `Conversation` objects that handle message history, context management, and persistence. **Integration with ChatBot**: - Automatically created by [`ChatBot.chat()`](`talk_box.ChatBot.chat`) - Returned by [`ChatBot.start_conversation()`](`talk_box.ChatBot.start_conversation`) - Updated by [`ChatBot.continue_conversation()`](`talk_box.ChatBot.continue_conversation`) This design ensures that users naturally discover conversation management capabilities through normal ChatBot usage, while providing advanced users direct access to conversation-level operations for specialized workflows. The class provides comprehensive functionality for message management, context window control, conversation persistence, and history analysis. It automatically handles chronological ordering, role-based filtering, and efficient context management for optimal AI performance. Conversations serve as containers for sequences of `Message` objects, providing both high-level convenience methods and fine-grained control over message operations. The class supports automatic context window management to stay within model limitations, conversation serialization for persistence, and extensive querying capabilities for conversation analysis and processing. Parameters ---------- conversation_id : str, optional Unique identifier for the conversation. If not provided, automatically generated using `uuid4()` to ensure global uniqueness. This enables reliable conversation tracking and referencing across systems and sessions. Returns ------- Conversation A new Conversation instance with empty message history and default settings. Core Message Operations ---------------------- The Conversation class provides multiple ways to add and manage messages: - [`add_message()`](`talk_box.Conversation.add_message`): Add a message with specified role - [`add_user_message()`](`talk_box.Conversation.add_user_message`): Add user messages - [`add_assistant_message()`](`talk_box.Conversation.add_assistant_message`): Add AI responses - [`add_system_message()`](`talk_box.Conversation.add_system_message`): Add system instructions - [`clear_messages()`](`talk_box.Conversation.clear_messages`): Remove all messages Message Retrieval and Filtering ------------------------------ Query and filter messages using flexible retrieval methods: - [`get_messages()`](`talk_box.Conversation.get_messages`): Get all or role-filtered messages - [`get_last_message()`](`talk_box.Conversation.get_last_message`): Get most recent message - [`get_message_count()`](`talk_box.Conversation.get_message_count`): Count total messages - [`get_context_messages()`](`talk_box.Conversation.get_context_messages`): Get messages within context window Context Window Management ------------------------ Control conversation length and model context efficiently: - [`set_context_window()`](`talk_box.Conversation.set_context_window`): Set maximum message count - [`get_context_messages()`](`talk_box.Conversation.get_context_messages`): Get messages within window Context windows automatically manage conversation length by keeping only the most recent messages when conversations exceed the specified limit. This ensures optimal performance with language models while preserving conversation continuity. Serialization and Persistence ---------------------------- Save and restore conversations using built-in serialization: - [`to_dict()`](`talk_box.Conversation.to_dict`): Convert to dictionary format - [`from_dict()`](`talk_box.Conversation.from_dict`): Create from dictionary data The serialization format preserves all conversation metadata, timestamps, and message history, enabling reliable persistence across sessions and systems. Examples -------- ### Creating and managing basic conversations Create a conversation and add messages using convenience methods: ```python from talk_box import Conversation # Create a new conversation conversation = Conversation() # Add messages using role-specific methods conversation.add_user_message("Hello! I need help with Python programming.") conversation.add_assistant_message("I'd be happy to help! What specific Python topic would you like to explore?") conversation.add_user_message("How do I create and use classes in Python?") print(f"Conversation has {len(conversation)} messages") print(f"Last message: {conversation.get_last_message().content}") ``` ### Working with system messages and context Use system messages to provide context and instructions: ```python # Create conversation with initial system context tech_conversation = Conversation() # Set up the assistant's behavior tech_conversation.add_system_message( "You are a senior Python developer. Provide detailed, practical answers with code examples." ) # Add conversation context tech_conversation.add_user_message( "I'm building a web API and need help with error handling.", metadata={"project": "web_api", "experience_level": "intermediate"} ) tech_conversation.add_assistant_message( "For robust API error handling, I recommend using structured exception handling...", metadata={"code_examples": True, "topics": ["exceptions", "api_design"]} ) # Get all assistant messages assistant_responses = tech_conversation.get_messages(role="assistant") print(f"Assistant provided {len(assistant_responses)} responses") ``` ### Context window management for long conversations Control conversation length to work within model limitations: ```python # Create conversation with context window long_conversation = Conversation() long_conversation.set_context_window(10) # Keep only last 10 messages # Add many messages (simulating a long conversation) for i in range(15): long_conversation.add_user_message(f"User message {i+1}") long_conversation.add_assistant_message(f"Assistant response {i+1}") # Check total vs context messages all_messages = long_conversation.get_messages() context_messages = long_conversation.get_context_messages() print(f"Total messages: {len(all_messages)}") print(f"Context messages: {len(context_messages)}") print(f"First context message: {context_messages[0].content}") ``` ### Conversation analysis and filtering Analyze conversation patterns and extract insights: ```python from datetime import datetime, timedelta # Create a conversation with varied message types analysis_conversation = Conversation() # Add messages with rich metadata analysis_conversation.add_user_message( "What's the weather like?", metadata={"intent": "weather_query", "urgency": "low"} ) analysis_conversation.add_assistant_message( "I don't have access to real-time weather data...", metadata={"capability": "limitation", "suggestion": "weather_api"} ) analysis_conversation.add_user_message( "Can you help me debug this code?", metadata={"intent": "code_help", "urgency": "high", "topic": "debugging"} ) # Analyze conversation patterns user_messages = analysis_conversation.get_messages(role="user") urgent_messages = [ msg for msg in user_messages if msg.metadata.get("urgency") == "high" ] code_related = [ msg for msg in analysis_conversation.get_messages() if "code" in msg.content.lower() or msg.metadata.get("topic") == "debugging" ] print(f"Urgent user requests: {len(urgent_messages)}") print(f"Code-related messages: {len(code_related)}") ``` ### Conversation persistence and restoration Save and restore conversations for session management: ```python import json from pathlib import Path # Create and populate a conversation original_conversation = Conversation() original_conversation.add_user_message("Save this conversation") original_conversation.add_assistant_message("I'll help you save this conversation data") # Serialize to dictionary conversation_data = original_conversation.to_dict() # Save to file (example - you might use databases, APIs, etc.) save_path = Path("conversation_backup.json") with save_path.open("w") as f: json.dump(conversation_data, f, indent=2) # Later: restore from file with save_path.open("r") as f: loaded_data = json.load(f) # Reconstruct conversation restored_conversation = Conversation.from_dict(loaded_data) print(f"Original ID: {original_conversation.conversation_id}") print(f"Restored ID: {restored_conversation.conversation_id}") print(f"Messages match: {len(original_conversation) == len(restored_conversation)}") # Clean up save_path.unlink() ``` ### Multi-turn conversation workflows Build complex conversation workflows with branching logic: ```python # Customer support conversation workflow support_conversation = Conversation() # Initial system setup support_conversation.add_system_message( "You are a helpful customer support agent. Gather information before providing solutions." ) # Customer inquiry support_conversation.add_user_message( "My order hasn't arrived yet", metadata={"category": "shipping", "sentiment": "concerned"} ) # Support response with information gathering support_conversation.add_assistant_message( "I understand your concern. Can you provide your order number so I can check the status?", metadata={"action": "information_gathering", "next_step": "order_lookup"} ) # Customer provides information support_conversation.add_user_message( "Order #12345", metadata={"order_id": "12345", "info_provided": True} ) # Check conversation flow last_assistant_msg = support_conversation.get_last_message(role="assistant") next_step = last_assistant_msg.metadata.get("next_step") print(f"Next action needed: {next_step}") # Determine conversation flow based on metadata user_messages = support_conversation.get_messages(role="user") has_order_info = any(msg.metadata.get("info_provided") for msg in user_messages) if has_order_info: support_conversation.add_assistant_message( "Thank you! I'm looking up order #12345 now...", metadata={"action": "order_lookup", "order_id": "12345"} ) ``` ### Integration with chatbot systems Use conversations as the foundation for chatbot interactions: ```python from talk_box import ChatBot # Create chatbot and conversation bot = ChatBot().preset("technical_advisor") bot_conversation = Conversation() # Set up conversation context bot_conversation.add_system_message( "You are a technical advisor specializing in Python and machine learning." ) # Simulate chat interaction def chat_with_bot(user_input: str) -> str: # Add user message bot_conversation.add_user_message(user_input) # Get bot response (simplified - real implementation would use bot.chat()) response = f"Technical response to: {user_input}" bot_conversation.add_assistant_message(response) return response # Use the chat function response1 = chat_with_bot("What is machine learning?") response2 = chat_with_bot("How do I start with scikit-learn?") print(f"Conversation now has {len(bot_conversation)} messages") print(f"Latest response: {bot_conversation.get_last_message().content}") ``` Advanced Features ---------------- **Message Metadata**: Each message can carry rich metadata for application-specific data, conversation analysis, and workflow management. **Automatic Timestamps**: All messages include creation timestamps for chronological analysis and conversation timeline reconstruction. **Context Management**: Intelligent context window handling ensures conversations stay within model limits while preserving important context. **Role-based Organization**: Standard roles (user, assistant, system, function) provide clear conversation structure for AI processing. **Extensible Design**: The conversation format supports custom roles, metadata schemas, and integration patterns for specialized use cases. **Memory Efficiency**: Context windows and message filtering enable efficient handling of very long conversations without memory issues. Integration Notes ---------------- - **Thread Safety**: Conversations are not thread-safe; use external synchronization for concurrent access - **Memory Usage**: Long conversations should use context windows to manage memory efficiently - **Serialization**: All message content and metadata must be JSON-serializable for persistence - **Timestamps**: Uses local time zone-naive datetime objects; consider UTC for distributed systems - **ID Uniqueness**: Conversation and message IDs are globally unique UUID4 strings The Conversation class provides the foundation for sophisticated conversational AI applications, enabling everything from simple chat interfaces to complex multi-turn workflows with rich context management and analysis capabilities. Message(content: str, role: str, timestamp: datetime.datetime = , metadata: dict[str, typing.Any] = , message_id: str = ) -> None Represents a single message in a conversational AI interaction, discovered through Conversation objects. The `Message` class is a fundamental data structure in Talk Box that users typically encounter when exploring `Conversation` objects returned by `ChatBot` methods. This creates a natural discovery path: `ChatBot` → `Conversation` → `Message`, where each layer provides progressively more detailed control over conversational AI interactions. **Discovery through the layered API**: 1. Start with [`ChatBot.chat()`](`talk_box.ChatBot.chat`) → returns `Conversation` 2. Explore [`Conversation.get_messages()`](`talk_box.Conversation.get_messages`) → returns list of `Message` 3. Access individual `Message` properties for detailed message inspection Each message encapsulates all information about individual exchanges in conversations, including text content, role information, timestamp data, and extensible metadata for storing additional context or processing information. Messages are immutable by design and include automatic timestamp generation and unique identification. The class supports serialization to and from dictionary format for storage, transmission, and integration with external systems. The role-based system follows standard conversational AI patterns where different participants in the conversation are clearly identified. Parameters ---------- content : str The actual text content of the message. This is the primary payload containing what was said or communicated in this message exchange. role : str The role of the message sender, indicating who or what generated this message. Standard roles include: - `"user"`: Messages from the human user - `"assistant"`: Messages from the AI chatbot or assistant - `"system"`: System-level messages, instructions, or metadata - `"function"`: Messages from function calls or tool executions Custom roles can be used for specialized conversation flows. timestamp : datetime, optional When the message was created. If not provided, automatically set to the current time using `datetime.now()`. This enables chronological ordering and time-based analysis of conversations. metadata : dict[str, Any], optional Additional metadata about the message as a dictionary. This extensible field can store any additional context, processing information, or custom data. Examples include token counts, confidence scores, source information, or custom application data. Defaults to an empty dictionary if not provided. message_id : str, optional Unique identifier for the message. If not provided, automatically generated using `uuid4()` to ensure global uniqueness. This enables reliable message referencing and tracking across systems. Returns ------- Message A new Message instance with the specified content and metadata. Message Serialization -------------------- Messages support full serialization to and from dictionary format for storage and transmission: - [`to_dict()`](`talk_box.Message.to_dict`): Convert to dictionary with ISO timestamp - [`from_dict()`](`talk_box.Message.from_dict`): Create from dictionary data The serialization format preserves all message information including timestamps and metadata, enabling reliable persistence and reconstruction. Examples -------- ### Creating basic messages Create messages for different conversation participants: ```python from talk_box import Message from datetime import datetime # User message - most common type user_msg = Message( content="What are the key principles of machine learning?", role="user" ) # Assistant response assistant_msg = Message( content="Machine learning has three key principles: representation, evaluation, and optimization...", role="assistant" ) # System instruction system_msg = Message( content="You are a helpful AI assistant specializing in technical topics.", role="system" ) print(f"User asked: {user_msg.content}") print(f"Message ID: {user_msg.message_id}") print(f"Created at: {user_msg.timestamp}") ``` ### Working with metadata Use metadata to store additional context and processing information: ```python # Message with rich metadata detailed_msg = Message( content="Here's the code implementation you requested...", role="assistant", metadata={ "model": "gpt-4-turbo", "tokens_used": 245, "confidence": 0.92, "sources": ["python_docs", "stackoverflow"], "code_blocks": 2, "execution_time": 1.3 } ) # Access metadata print(f"Model used: {detailed_msg.metadata['model']}") print(f"Confidence: {detailed_msg.metadata['confidence']}") print(f"Sources: {', '.join(detailed_msg.metadata['sources'])}") ``` ### Message serialization and persistence Convert messages to/from dictionaries for storage and transmission: ```python # Create a message original_msg = Message( content="Serialize this message for storage", role="user", metadata={"importance": "high", "category": "technical"} ) # Convert to dictionary (for JSON storage, API calls, etc.) msg_dict = original_msg.to_dict() print("Serialized message:", msg_dict) # Reconstruct from dictionary restored_msg = Message.from_dict(msg_dict) print(f"Restored content: {restored_msg.content}") print(f"Same message ID: {restored_msg.message_id == original_msg.message_id}") ``` ### Function call messages Create messages for function calls and tool usage: ```python # Function call request function_call = Message( content="calculate_statistics", role="function", metadata={ "function_name": "calculate_statistics", "arguments": {"data": [1, 2, 3, 4, 5], "method": "mean"}, "call_id": "func_001" } ) # Function result function_result = Message( content="Statistics calculated: mean=3.0, std=1.58", role="function", metadata={ "function_name": "calculate_statistics", "result": {"mean": 3.0, "std": 1.58}, "call_id": "func_001", "success": True } ) print(f"Function: {function_call.metadata['function_name']}") print(f"Result: {function_result.content}") ``` ### Custom roles and specialized workflows Use custom roles for specialized conversation types: ```python # Code review workflow code_submission = Message( content="def fibonacci(n): return n if n <= 1 else fibonacci(n-1) + fibonacci(n-2)", role="developer" ) code_review = Message( content="Consider using memoization to improve performance for large n values.", role="reviewer", metadata={ "review_type": "performance", "severity": "suggestion", "line_numbers": [1] } ) # Documentation workflow doc_request = Message( content="Please document the fibonacci function", role="doc_manager" ) documentation = Message( content="Calculates the nth Fibonacci number using recursive approach...", role="technical_writer", metadata={ "doc_type": "function_docstring", "coverage": "complete" } ) ``` ### Message validation and filtering Messages can be validated and filtered based on their attributes: ```python messages = [user_msg, assistant_msg, system_msg, detailed_msg] # Filter by role user_messages = [msg for msg in messages if msg.role == "user"] assistant_messages = [msg for msg in messages if msg.role == "assistant"] # Filter by metadata presence messages_with_metadata = [msg for msg in messages if msg.metadata] # Filter by timestamp (messages from last hour) from datetime import timedelta recent_cutoff = datetime.now() - timedelta(hours=1) recent_messages = [msg for msg in messages if msg.timestamp > recent_cutoff] print(f"User messages: {len(user_messages)}") print(f"Messages with metadata: {len(messages_with_metadata)}") print(f"Recent messages: {len(recent_messages)}") ``` ### Integration with conversation systems Messages are designed to integrate seamlessly with conversation management: ```python from talk_box import Conversation # Create conversation and add messages conversation = Conversation() # Add messages directly conversation.add_message("Hello, I need help with Python", "user") conversation.add_message("I'd be happy to help! What specific topic?", "assistant") # Or add pre-created Message objects detailed_question = Message( content="How do I implement a binary search algorithm?", role="user", metadata={"topic": "algorithms", "difficulty": "intermediate"} ) conversation.messages.append(detailed_question) print(f"Conversation has {len(conversation)} messages") ``` Design Notes ----------- - **Immutability**: Messages are dataclasses and should be treated as immutable after creation - **Timestamps**: All timestamps are timezone-naive datetime objects in local time - **Unique IDs**: Message IDs are UUID4 strings, globally unique across all systems - **Metadata Flexibility**: Metadata dictionaries can contain any JSON-serializable data - **Role Standards**: While standard roles are recommended, custom roles are fully supported - **Serialization Safety**: All fields serialize safely to JSON via the `to_dict()` method The Message class provides the foundation for all conversational AI interactions in Talk Box, enabling rich, traceable, and extensible communication between users and AI systems. ## ChatBot Methods Configuration and interaction methods for the ChatBot class model(self, model_name: str) -> 'ChatBot' Configure the language model to use for generating responses. Sets the specific language model that will be used when the chatbot generates responses. This method supports models from various providers including OpenAI, Anthropic, Google, and others through the chatlas integration. The model choice significantly impacts response quality, speed, cost, and capabilities. The chatbot automatically detects the appropriate provider based on the model name and handles authentication via environment variables. Different models have different strengths as some excel at reasoning, others at creativity, and others at specific domains like code generation. Parameters ---------- model_name The name of the language model to use. Exact model names may vary by provider. Check provider documentation for the most current model names and capabilities. Returns ------- ChatBot Returns self to enable method chaining, allowing you to configure multiple parameters in a single fluent expression. Raises ------ ValueError If the model name is empty or None. The method does not validate model availability at configuration time. Validation occurs when creating chat sessions. Model Types by Provider ------------------------ Here are some examples of model types by provider: **OpenAI Models:** - `"gpt-4o"`: latest multimodal model with excellent capabilities - `"gpt-4-turbo"`: GPT-4 with improved performance and lower cost - `"gpt-4"`: Original GPT-4 model with excellent reasoning capabilities - `"gpt-3.5-turbo"`: fast, cost-effective model good for most tasks (default) **Anthropic Models:** - `"claude-sonnet-4-6"`: Claude model with excellent reasoning - `"claude-haiku-4-5"`: fast, efficient model for simple tasks - `"claude-opus-4-7"`: very capable Claude model for complex tasks **Google Models:** - `"gemini-pro"`: The flagship model from Google Examples -------- ### Using different models for different purposes Configure chatbots with models optimized for specific tasks: ```python import talk_box as tb # High-performance model for complex reasoning reasoning_bot = tb.ChatBot().model("gpt-4-turbo") # Default balanced model (recommended starting point) balanced_bot = tb.ChatBot().model("gpt-3.5-turbo") # Fast, cost-effective model for simple tasks quick_bot = tb.ChatBot().model("gpt-3.5-turbo") # Creative model for storytelling creative_bot = tb.ChatBot().model("claude-opus-4-7") # Multimodal model for image analysis vision_bot = tb.ChatBot().model("gpt-4o") ``` ### Model selection with method chaining Combine model selection with other configuration options: ```python import talk_box as tb # Technical advisor with high-performance model tech_bot = ( tb.ChatBot() .model("gpt-4-turbo") .preset("technical_advisor") .temperature(0.2) # Low creativity for factual responses .max_tokens(2000) ) # Creative writer with Claude writer_bot = ( tb.ChatBot() .model("claude-opus-4-7") .preset("creative_writer") .temperature(0.8) # High creativity .persona("Imaginative storyteller with rich vocabulary") ) ``` ### Dynamic model switching Change models based on task requirements: ```python import talk_box as tb bot = tb.ChatBot().preset("technical_advisor") # Use fast model for quick questions bot.model("gpt-3.5-turbo") quick_response = bot.chat("What is Python?") # Switch to powerful model for complex analysis bot.model("gpt-4-turbo") detailed_response = bot.chat("Explain the architectural trade-offs between microservices and monoliths") ``` ### Model capabilities and selection guide Choose models based on your specific requirements: ```python import talk_box as tb # For code generation and technical tasks code_bot = tb.ChatBot().model("gpt-4-turbo").preset("technical_advisor") # For creative writing and storytelling creative_bot = tb.ChatBot().model("claude-opus-4-7").preset("creative_writer") # For cost-effective general tasks general_bot = tb.ChatBot().model("gpt-3.5-turbo").preset("customer_support") # For multimodal tasks (text + images) vision_bot = tb.ChatBot().model("gpt-4o") ``` Notes ----- **Provider Authentication**: ensure appropriate API keys are set in environment variables (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`) for the chosen model provider. **Model Availability**: model availability may change over time. Check provider documentation for current model names and deprecation schedules. **Cost Considerations**: different models have different pricing structures. Consider cost implications for production deployments. **Rate Limits**: each model/provider has different rate limits. Plan accordingly for high-volume applications. **Context Windows**: models have different maximum context window sizes, affecting how much conversation history can be included in requests. See Also -------- preset : Apply behavior presets that work well with specific models temperature : Control response randomness and creativity max_tokens : Set response length limits appropriate for the chosen model provider_model(self, provider_model: str) -> 'ChatBot' Set provider and model using a single string (e.g., "openai:gpt-4o"). This method provides a convenient way to configure both the AI provider and model in a single call using a colon-separated format. This is especially useful when you want to explicitly specify the provider or when working with models from different providers that might have similar names. Parameters ---------- provider_model String in the format `"provider:model"` (e.g., `"openai:gpt-4o"`, `"anthropic:claude-3-opus"`). If only a model name is provided without a colon, defaults to OpenAI provider. Returns ------- ChatBot Returns self for method chaining, allowing you to configure multiple parameters in a single fluent expression. Raises ------ ValueError If the `provider_model=` string is empty, `None`, or improperly formatted. Examples -------- ### Using explicit provider and model combinations ```python import talk_box as tb # OpenAI models openai_bot = tb.ChatBot().provider_model("openai:gpt-4o") # Anthropic models anthropic_bot = tb.ChatBot().provider_model("anthropic:claude-opus-4-7") # Google models google_bot = tb.ChatBot().provider_model("google:gemini-pro") # Default to OpenAI if no provider specified default_bot = tb.ChatBot().provider_model("gpt-4-turbo") ``` ### Method chaining with provider_model ```python # Complete configuration with explicit provider bot = ( ChatBot() .provider_model("anthropic:claude-opus-4-7") .preset("technical_advisor") .temperature(0.2) .max_tokens(2000) ) ``` Notes ----- **Provider Authentication**: ensure appropriate API keys are set in environment variables for the specified provider (e.g., `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`). **Provider Detection**: when only a model name is provided, the system defaults to OpenAI. For other providers, always specify the provider explicitly. See Also -------- model : Set just the model name (uses default provider detection) preset : Apply behavior presets that work well with specific provider/model combinations preset(self, preset_name: Union[str, ForwardRef('PresetNames')]) -> 'ChatBot' Apply a pre-configured behavior template to instantly specialize the chatbot. Presets are professionally crafted behavior templates that instantly configure multiple aspects of the chatbot including conversational tone, expertise areas, response verbosity, operational constraints, and system prompts. This provides a quick way to create specialized chatbots for specific domains without manually configuring each parameter. The preset system includes a curated library of templates covering common use cases like customer support, technical advisory, creative writing, data analysis, and legal information. Each preset is designed by experts to provide optimal performance for its intended domain while maintaining flexibility for customization. When a preset is applied, it sets default values for various configuration parameters. You can still override individual settings after applying a preset, allowing for both rapid deployment and fine-tuned customization. Parameters ---------- preset_name The name of the behavior preset to apply. You can use either a string or a constant from `PresetNames` for better autocomplete and type safety. **Using PresetNames constants (recommended):** ```python import talk_box as tb bot = tb.ChatBot().preset(tb.PresetNames.TECHNICAL_ADVISOR) ``` See the "Available Presets" section below for a complete list of available presets and their descriptions. Returns ------- ChatBot Returns self to enable method chaining, allowing you to combine preset application with other configuration methods. Raises ------ ValueError If the preset name is not found in the available preset library. The method fails gracefully and continues if preset loading encounters issues. Available Presets ----------------- The Talk Box framework includes professionally crafted presets for common use cases: **Business and Support:** - `PresetNames.CUSTOMER_SUPPORT` or `"customer_support"`: polite, professional customer service interactions with concise responses and helpful guidance - `PresetNames.LEGAL_ADVISOR` or `"legal_advisor"`: professional legal information with appropriate disclaimers and thorough, well-sourced responses **Technical and Development:** - `PresetNames.TECHNICAL_ADVISOR` or `"technical_advisor"`: authoritative technical guidance with detailed explanations, code examples, and best practices - `PresetNames.DATA_ANALYST` or `"data_analyst"`: analytical, evidence-based responses for data science and statistical analysis tasks **Creative and Content:** - `PresetNames.CREATIVE_WRITER` or `"creative_writer"`: imaginative storytelling and creative content generation with descriptive, engaging responses Additional presets may be available through custom preset libraries or organizational preset collections. Examples -------- ### Using default presets for common scenarios Apply presets for different types of interactions: ```python import talk_box as tb # Customer support chatbot support_bot = ( tb.ChatBot() .preset("customer_support") .model("gpt-3.5-turbo") # Fast, cost-effective for support ) # Technical advisor for development questions tech_bot = ( tb.ChatBot() .preset("technical_advisor") .model("gpt-4-turbo") # Powerful model for complex technical questions ) # Creative writing assistant writer_bot = ( tb.ChatBot() .preset("creative_writer") .model("claude-opus-4-7") # Excellent for creative tasks ) ``` ### Combining presets with custom configuration Start with a preset and customize specific aspects: ```python # Start with technical advisor preset, then customize specialized_bot = ( tb.ChatBot() .preset("technical_advisor") .persona("Senior Python developer specializing in web frameworks") .temperature(0.1) # Very low randomness for precise technical answers .tools(["code_executor", "documentation_search"]) .avoid(["deprecated_practices", "insecure_patterns"]) ) # Customer support with custom personality friendly_support = ( tb.ChatBot() .preset("customer_support") .persona("Enthusiastic and empathetic customer advocate") .verbose(True) # Detailed explanations for complex issues ) ``` ### Preset-specific optimizations Different presets work better with specific models and settings: ```python # Data analyst with analytical model and settings analyst_bot = ( tb.ChatBot() .preset("data_analyst") .model("gpt-4-turbo") # Strong reasoning capabilities .temperature(0.2) # Low creativity, high accuracy .max_tokens(2000) # Allow detailed analysis ) # Creative writer with creative model and settings creative_bot = ( tb.ChatBot() .preset("creative_writer") .model("claude-opus-4-7") # Excellent creative capabilities .temperature(0.8) # High creativity .max_tokens(3000) # Allow longer creative outputs ) ``` ### Inspecting preset configuration View what a preset configures before applying it: ```python # Get preset details manager = tb.PresetManager() tech_preset = manager.get_preset("technical_advisor") if tech_preset: print(f"Tone: {tech_preset.tone}") print(f"Expertise: {tech_preset.expertise}") print(f"Verbosity: {tech_preset.verbosity}") print(f"Constraints: {', '.join(tech_preset.constraints)}") # Apply preset and check final configuration bot = tb.ChatBot().preset("technical_advisor") config = bot.get_config() print(f"Final config: {config}") ``` ### Dynamic preset switching Change presets based on conversation context: ```python # Start with customer support bot = tb.ChatBot().preset("customer_support") # Handle general customer inquiry response1 = bot.chat("I need help with my order") # Switch to technical advisor for technical questions bot.preset("technical_advisor") response2 = bot.chat("How do I integrate your API?") # Switch to data analyst for analytics questions bot.preset("data_analyst") response3 = bot.chat("What patterns do you see in our user data?") ``` Preset Customization ------------------- **Individual Override**: all preset settings can be overridden by calling the corresponding configuration methods after applying the preset. **Custom Presets**: organizations can create custom presets using the `PresetManager` to add domain-specific behavior templates. **Preset Inheritance**: advanced implementations can create preset hierarchies where specialized presets extend base presets with additional configuration. **Context Awareness**: some presets include conditional logic in their system prompts that adapts behavior based on conversation context. Notes ----- **Preset Loading**: presets are loaded from the `PresetManager` which initializes with a default library and can be extended with custom presets. **Graceful Failure**: if a preset is not found or fails to load, the method continues without error, allowing the chatbot to function with default settings. **System Prompts**: each preset includes carefully crafted system prompts that provide detailed behavioral instructions to the underlying language model. **Best Practices**: choose presets that match your intended use case, then fine-tune with additional configuration methods as needed. See Also -------- PresetManager : Manage and create custom behavior presets persona : Add custom personality traits on top of preset behavior model : Choose models that work well with specific presets temperature : Adjust creativity levels appropriate for the preset domain temperature(self, temp: float) -> 'ChatBot' Control the randomness and creativity level of chatbot responses. Temperature is a crucial parameter that controls the balance between deterministic accuracy and creative variability in language model outputs. Lower temperatures produce more focused, consistent, and predictable responses, while higher temperatures encourage more diverse, creative, and exploratory outputs at the potential cost of accuracy. The temperature parameter directly affects the probability distribution over possible next tokens during text generation. At temperature `0`, the model always selects the most likely next token, resulting in deterministic outputs. Higher temperatures flatten the probability distribution, allowing less likely but potentially more creative tokens to be selected. Understanding temperature is essential for fine-tuning chatbot behavior to match specific use cases, from precise technical assistance to creative brainstorming and content generation. Parameters ---------- temp The temperature value controlling response randomness, typically ranging from `0.0` to `2.0`. Lower values produce more deterministic and consistent responses, while higher values encourage creativity and variability. See the "Temperature Ranges" section below for detailed guidance. Returns ------- ChatBot Returns self to enable method chaining, allowing you to combine temperature setting with other configuration methods. Raises ------ ValueError If temperature is negative or excessively high (typically > `2.0`), though exact limits depend on the underlying model provider. Temperature Ranges ------------------ Choose temperature values based on your specific use case requirements: **Ultra-Low (`0.0`-`0.2`):** - `0.0`: completely deterministic, always chooses most likely response - `0.1`: near-deterministic with minimal variation - `0.2`: highly consistent with occasional minor variations - Best for: code generation, mathematical calculations, factual Q&A **Low (`0.3`-`0.5`):** - `0.3`: consistent with slight creative touches - `0.4`: balanced consistency with controlled variation - `0.5`: moderate creativity while maintaining reliability - Best for: technical documentation, structured analysis, tutorials **Medium (`0.6`-`0.8`):** - `0.6`: balanced creativity and consistency - `0.7`: default setting for most general-purpose applications - `0.8`: enhanced creativity with good coherence - Best for: conversational AI, content writing, explanations **High (`0.9`-`1.2`):** - `0.9`: creative responses with acceptable coherence - `1.0`: high creativity, more diverse phrasings - `1.2`: very creative, potentially unexpected responses - Best for: brainstorming, creative writing, ideation **Ultra-High (`1.3`-`2.0`):** - `1.5`: highly experimental and creative outputs - `2.0`: maximum creativity, potentially incoherent - Best for: artistic exploration, experimental content Values above `2.0` are generally not recommended as they may produce incoherent or nonsensical responses. Examples -------- ### Temperature for different use cases Configure temperature based on your specific needs: ```python import talk_box as tb # Ultra-precise for code generation and technical tasks code_bot = ( tb.ChatBot() .model("gpt-4-turbo") .temperature(0.0) # Deterministic outputs .preset("technical_advisor") ) # Balanced for general conversation general_bot = ( tb.ChatBot() .model("gpt-3.5-turbo") .temperature(0.7) # Default balanced setting ) # Creative for content generation creative_bot = ( tb.ChatBot() .model("claude-opus-4-7") .temperature(1.0) # High creativity .preset("creative_writer") ) ``` ### Precision vs. creativity trade-offs Demonstrate the impact of different temperature settings: ```python # For mathematical calculations: use minimal temperature math_bot = ( tb.ChatBot() .temperature(0.1) .persona("Mathematics tutor focused on step-by-step solutions") ) # For brainstorming: use higher temperature brainstorm_bot = ( tb.ChatBot() .temperature(1.1) .persona("Creative strategist generating innovative ideas") ) # For customer support: balanced approach support_bot = ( tb.ChatBot() .temperature(0.4) .preset("customer_support") .persona("Helpful and consistent customer service representative") ) ``` ### Domain-specific temperature optimization Adjust temperature for specific professional domains: ```python # Legal analysis: high precision required legal_bot = ( tb.ChatBot() .preset("legal_advisor") .temperature(0.2) # Low creativity, high accuracy .model("gpt-4-turbo") ) # Marketing content: creative but controlled marketing_bot = ( tb.ChatBot() .temperature(0.8) # Creative but coherent .persona("Brand-aware marketing specialist") .avoid(["generic_language", "cliches"]) ) # Data analysis: analytical precision analyst_bot = ( tb.ChatBot() .preset("data_analyst") .temperature(0.3) # Consistent analytical approach .tools(["statistical_analysis", "data_visualization"]) ) ``` ### Dynamic temperature adjustment Adapt temperature based on conversation context: ```python class AdaptiveBot: def __init__(self): self.bot = tb.ChatBot().model("gpt-4-turbo") def answer_question(self, question: str, question_type: str): if question_type == "factual": self.bot.temperature(0.1) # High precision elif question_type == "creative": self.bot.temperature(1.0) # High creativity elif question_type == "analytical": self.bot.temperature(0.3) # Balanced analysis else: self.bot.temperature(0.7) # Default return self.bot.chat(question) # Usage adaptive = AdaptiveBot() # Factual question with low temperature factual_response = adaptive.answer_question( "What is the capital of France?", "factual" ) # Creative question with high temperature creative_response = adaptive.answer_question( "Write a haiku about machine learning", "creative" ) ``` ### Temperature with model-specific considerations Different models respond differently to temperature settings: ```python # GPT models: standard temperature ranges gpt_bot = ( tb.ChatBot() .model("gpt-4-turbo") .temperature(0.7) # Works well with GPT models ) # Claude models: may handle higher temperatures better claude_bot = ( tb.ChatBot() .model("claude-opus-4-7") .temperature(0.9) # Claude often maintains coherence at higher temps ) # Local models: may need different calibration local_bot = ( tb.ChatBot() .model("llama-2-13b-chat") .temperature(0.5) # Conservative for smaller models ) ``` ### A/B testing different temperatures Compare response quality across temperature settings: ```python def compare_temperatures(question: str, temperatures: list[float]): """Compare the same question across different temperatures.""" results = {} for temp in temperatures: bot = ( tb.ChatBot() .model("gpt-4-turbo") .temperature(temp) ) response = bot.chat(question) results[temp] = response return results # Test different temperatures question = "Explain quantum computing in simple terms" temps = [0.2, 0.5, 0.8, 1.1] comparison = compare_temperatures(question, temps) for temp, response in comparison.items(): print(f"Temperature {temp}:") print(f"{response.content[:100]}...") print() ``` Temperature Guidelines ---------------------- **Code Generation**: Use `0.0`-`0.2` for precise, syntactically correct code with minimal variation. **Technical Writing**: Use `0.2`-`0.4` for accurate, consistent technical documentation and explanations. **General Conversation**: Use `0.6`-`0.8` for natural, engaging dialogue with appropriate variation. **Creative Content**: Use `0.8`-`1.2` for storytelling, marketing copy, and creative ideation. **Brainstorming**: Use `1.0`-`1.5` for maximum idea diversity and out-of-the-box thinking. Model Considerations -------------------- **Provider Differences**: different AI providers may interpret temperature values differently, so test with your specific model. **Model Size**: larger models often handle higher temperatures better while maintaining coherence. **Fine-tuned Models**: custom fine-tuned models may have different optimal temperature ranges compared to base models. **Context Length**: longer conversations may benefit from slightly lower temperatures to maintain consistency. Notes ----- **Reproducibility**: use temperature `0.0` for reproducible outputs across multiple runs with the same input. **Gradual Adjustment**: when uncertain, start with default (`0.7`) and adjust incrementally based on response quality. **Task Specificity**: consider the specific requirements of your task when choosing temperature (accuracy vs. creativity trade-offs). **Monitoring**: monitor response quality when adjusting temperature, as optimal values may vary by use case and model. See Also -------- max_tokens : Control response length alongside creativity model : Different models respond differently to temperature preset : Presets often include optimized temperature settings persona : Personality can complement temperature settings max_tokens(self, tokens: int) -> 'ChatBot' Set the maximum number of tokens for chatbot responses. The `max_tokens()` option controls the maximum length of generated responses by limiting the number of tokens (roughly equivalent to words and punctuation) that the language model can produce in a single response. This is crucial for managing response length, controlling costs, ensuring consistent behavior, and preventing excessively long outputs that might overwhelm users or exceed system limits. Understanding token limits is essential for balancing response completeness with practical constraints. Different models have varying token counting methods and maximum context windows, making this parameter both a performance optimization tool and a cost management mechanism. Token counting varies by model and provider, but generally: - 1 token ≈ 0.75 English words - 100 tokens ≈ 75 words or ~1-2 sentences - 500 tokens ≈ 375 words or ~1-2 paragraphs - 1000 tokens ≈ 750 words or ~1 page of text Parameters ---------- tokens Maximum number of tokens for response generation. Must be positive. See the "Token Usage Guidelines" section below for detailed recommendations and model-specific limits. Returns ------- ChatBot Returns self to enable method chaining, allowing you to combine max_tokens setting with other configuration methods. Raises ------ ValueError If tokens is not a positive integer. Some models may also have specific upper limits that could trigger additional validation errors. Token Usage Guidelines ---------------------- Choose token limits based on your specific use case and content requirements: **Short Responses (50-200 tokens):** - quick answers, confirmations, brief explanations - customer support acknowledgments - code snippets and short technical answers - chat-style interactions **Medium Responses (200-800 tokens):** - detailed explanations and tutorials - code documentation and examples - product descriptions and feature explanations - structured analysis and recommendations **Long Responses (800-2000 tokens):** - comprehensive guides and documentation - detailed technical analysis - creative writing and storytelling - in-depth research summaries **Extended Responses (2000+ tokens):** - long-form content generation - detailed reports and documentation - comprehensive tutorials and guides - complex analysis requiring extensive explanation **Model-Specific Limits:** Different models have varying maximum context windows (shared between input and output): - GPT-3.5-turbo: up to 4,096 tokens total - GPT-4: up to 8,192 tokens total - GPT-4-turbo: up to 128,000 tokens total - Claude-3: up to 200,000 tokens total Examples -------- ### Setting tokens for different response types Configure max_tokens based on your expected response length: ```python import talk_box as tb # Brief answers for quick interactions quick_bot = ( tb.ChatBot() .model("gpt-3.5-turbo") .max_tokens(150) # ~100-120 words .preset("customer_support") ) # Detailed explanations for technical questions detailed_bot = ( tb.ChatBot() .model("gpt-4-turbo") .max_tokens(1000) # ~750 words .preset("technical_advisor") ) # Long-form content generation content_bot = ( tb.ChatBot() .model("claude-opus-4-7") .max_tokens(3000) # ~2250 words .preset("creative_writer") ) ``` ### Balancing completeness with constraints Optimize token limits for specific scenarios: ```python # Code generation: precise and concise code_bot = ( tb.ChatBot() .model("gpt-4-turbo") .max_tokens(500) # Focus on essential code .temperature(0.1) .persona("Senior software engineer providing clean, efficient code") ) # Documentation writing: comprehensive but structured docs_bot = ( tb.ChatBot() .model("gpt-4-turbo") .max_tokens(1500) # Detailed but focused .temperature(0.3) .persona("Technical writer creating clear, comprehensive documentation") ) # Creative writing: longer form allowed story_bot = ( tb.ChatBot() .model("claude-opus-4-7") .max_tokens(2500) # Allow creative expression .temperature(0.9) .preset("creative_writer") ) ``` ### Dynamic token adjustment based on context Adapt max_tokens based on conversation needs: ```python class AdaptiveTokenBot: def __init__(self): self.bot = tb.ChatBot().model("gpt-4-turbo") def respond(self, message: str, response_type: str): if response_type == "brief": self.bot.max_tokens(200) # Quick answers elif response_type == "detailed": self.bot.max_tokens(1000) # Thorough explanations elif response_type == "comprehensive": self.bot.max_tokens(2000) # In-depth analysis else: self.bot.max_tokens(500) # Default moderate length return self.bot.chat(message) # Usage examples adaptive = AdaptiveTokenBot() # Brief response for simple questions quick_answer = adaptive.respond( "What is Python?", "brief" ) # Detailed response for complex topics detailed_answer = adaptive.respond( "Explain machine learning algorithms", "detailed" ) ``` ### Cost optimization with token limits Use max_tokens to control API costs: ```python # Cost-conscious configuration for high-volume usage efficient_bot = ( tb.ChatBot() .model("gpt-3.5-turbo") # Lower cost model .max_tokens(300) # Limit response length .temperature(0.5) # Balanced creativity ) # Premium configuration for important interactions premium_bot = ( tb.ChatBot() .model("gpt-4-turbo") .max_tokens(1500) # Allow detailed responses .temperature(0.7) ) # Budget tracking example def cost_aware_chat(message: str, budget_tier: str): if budget_tier == "economy": bot = tb.ChatBot().model("gpt-3.5-turbo").max_tokens(200) elif budget_tier == "standard": bot = tb.ChatBot().model("gpt-4").max_tokens(500) else: # premium bot = tb.ChatBot().model("gpt-4-turbo").max_tokens(1500) return bot.chat(message) ``` ### Token limits for different content types Optimize based on content format requirements: ```python # Email responses: professional length email_bot = ( tb.ChatBot() .max_tokens(400) # Professional email length .persona("Professional and concise business communicator") .preset("customer_support") ) # Blog post generation: substantial content blog_bot = ( tb.ChatBot() .max_tokens(2000) # Article-length content .temperature(0.8) .persona("Engaging content writer") ) # Social media responses: very brief social_bot = ( tb.ChatBot() .max_tokens(100) # Tweet-length responses .temperature(0.7) .persona("Friendly and engaging social media manager") ) # Technical documentation: comprehensive tech_docs_bot = ( tb.ChatBot() .max_tokens(1800) # Detailed technical content .temperature(0.2) .preset("technical_advisor") ) ``` ### Monitoring token usage Track actual vs. maximum token usage: ```python def monitor_token_usage(messages: list[str], max_tokens: int): """Monitor actual token usage vs. limits.""" bot = tb.ChatBot().model("gpt-4-turbo").max_tokens(max_tokens) usage_data = [] for message in messages: response = bot.chat(message) # Note: Actual token counting would require model-specific methods estimated_tokens = len(response.content.split()) * 1.3 # Rough estimate usage_data.append({ "message": message[:50] + "..." if len(message) > 50 else message, "max_tokens": max_tokens, "estimated_used": int(estimated_tokens), "utilization": f"{(estimated_tokens/max_tokens)*100:.1f}%" }) return usage_data # Example usage test_messages = [ "What is artificial intelligence?", "Explain quantum computing in detail", "Write a short poem about technology" ] usage_report = monitor_token_usage(test_messages, 500) for entry in usage_report: print(f"Message: {entry['message']}") print(f"Utilization: {entry['utilization']}") print() ``` Token Management Best Practices ------------------------------- **Start Conservative**: begin with lower token limits and increase as needed to avoid unexpectedly long responses. **Content-Specific Limits**: set different limits for different types of content (code, explanations, creative writing, etc.). **Cost Monitoring**: use token limits as a cost control mechanism, especially for high-volume applications. **User Experience**: balance completeness with readability as very long responses can overwhelm users. **Model Considerations**: different models have different token counting methods and optimal ranges. Performance Implications ------------------------ **Response Time**: higher token limits may increase response generation time, especially for complex requests. **Cost Scaling**: most API providers charge based on token usage, making this parameter directly tied to operational costs. **Context Window**: remember that max_tokens is shared with input tokens in most models' context windows. **Completion Quality**: very low token limits may result in incomplete responses, while very high limits may lead to verbose, unfocused outputs. Notes ----- **Model Variations**: different models count tokens differently and have varying optimal token ranges for quality output. **Shared Context**: in most models, max_tokens counts toward the total context window, which includes both input and output tokens. **Truncation Behavior**: when a response reaches the max_tokens limit, it is typically truncated, which may result in incomplete sentences or thoughts. **Dynamic Adjustment**: consider implementing dynamic token adjustment based on response type, user preferences, or conversation context. See Also -------- model : Different models have different token limits and behavior temperature : Balance creativity with token efficiency preset : Some presets include optimized token settings tools : Tool usage may affect token consumption patterns persona(self, persona_description: str) -> 'ChatBot' Set a persona that shapes the chatbot's tone and behavior. The persona string becomes the opening identity statement in the constructed system prompt (e.g., "You are {persona_description}"). It occupies the highest-attention primacy position, so it strongly influences all subsequent responses. Parameters ---------- persona_description A natural-language description of who the chatbot should be. Can range from a short role label (`"a helpful assistant"`) to a multi-sentence character brief. Returns ------- ChatBot The same instance for method chaining. Examples -------- ```{python} import talk_box as tb bot = tb.ChatBot().persona("a senior Python developer") bot.get_config()["persona"] ``` system_prompt(self, prompt: Union[str, ForwardRef('PromptBuilder')]) -> 'ChatBot' Set a custom system prompt, overriding any preset system prompt. This method allows for fine-grained prompt engineering. The custom system prompt will take precedence over any preset system prompt, though it will still be combined with persona, constraints, and other configuration elements. Three Approaches to System Prompt Creation ------------------------------------------ **Direct String Approach**: pass a complete system prompt as a single string. This is straightforward for simple prompts or when adapting existing prompts. **ChatBot.prompt_builder() Method (Recommended)**: use the attention-optimized `prompt_builder()` method from a ChatBot instance. This provides better structure, maintainability, and leverages modern prompt engineering research on attention patterns. **`PromptBuilder` Class**: use the `PromptBuilder` class directly for maximum flexibility and reusable prompt templates that can be used across multiple `ChatBot` instances. The structured prompt approaches (methods 2 and 3) are especially valuable for: - complex multi-section prompts - professional domain specializations - prompts requiring consistent structure across variations - team environments where prompt templates need to be maintainable - reusable prompt templates across different chatbot configurations Parameters ---------- prompt The custom system prompt text. Can include prompt engineering techniques, specific instructions, formatting requirements, etc. Returns ------- ChatBot Returns self for method chaining Examples -------- ### Comparing the three approaches **Direct String Approach**: simple and direct: ```python import talk_box as tb # Quick setup with string prompt bot = tb.ChatBot().model("gpt-4-turbo").system_prompt( "You are a helpful Python tutor. Always provide working code examples " "and explain the reasoning behind each solution." ) ``` **ChatBot.prompt_builder() Method**: structured and maintainable: ```python import talk_box as tb # Same functionality with better structure bot = tb.ChatBot().model("gpt-4-turbo") # Build an attention-optimized prompt prompt = ( bot.prompt_builder() .persona("helpful Python tutor", "educational programming assistance") .core_analysis(["Provide working code examples", "Explain reasoning behind solutions"]) .output_format(["Clear step-by-step explanations", "Commented code examples"]) ._build() ) # Apply the structured prompt bot.system_prompt(prompt) ``` **PromptBuilder Class Directly**: maximum flexibility and reusability: ```python import talk_box as tb # Create reusable prompt template python_tutor_template = ( tb.PromptBuilder() .persona("helpful Python tutor", "educational programming assistance") .core_analysis(["Provide working code examples", "Explain reasoning behind solutions"]) .output_format(["Clear step-by-step explanations", "Commented code examples"]) ._build() ) # Use the same template across multiple bots beginner_bot = tb.ChatBot().model("gpt-3.5-turbo").system_prompt(python_tutor_template) advanced_bot = tb.ChatBot().model("gpt-4-turbo").system_prompt(python_tutor_template) ``` ### Why structured approaches are recommended for complex prompts **For complex professional domains, structured prompt building provides superior results:** ```python import talk_box as tb # Create a security code reviewer with attention-optimized structure bot = tb.ChatBot().model("gpt-4-turbo") security_prompt = ( bot.prompt_builder() .persona("senior security engineer", "application security code review") .task_context("Comprehensive security review following OWASP methodology") .critical_constraint("Prioritize security vulnerabilities over style issues") .core_analysis([ "Input validation and sanitization", "Authentication and authorization controls", "Secure data handling (encryption, PII protection)", "Error handling (no sensitive info in errors)", "Dependencies and third-party library security" ]) .output_format([ "🚨 CRITICAL ISSUES: Security vulnerabilities with CVSS scores", "⚠️ HIGH PRIORITY: Logic errors and architectural problems", "📈 IMPROVEMENTS: Performance and maintainability suggestions" ]) .final_emphasis("Professional, constructive tone with educational explanations") ._build() ) bot.system_prompt(security_prompt) ``` **Benefits of this structured approach:** - clear attention hierarchy (critical info first) - maintainable and modifiable sections - consistent output format across reviews - research-backed attention optimization ### Using `PromptBuilder` class for reusable templates **The direct `PromptBuilder` class approach excels for template reuse across teams:** ```python import talk_box as tb # Create a reusable code review template code_review_template = ( tb.PromptBuilder() .persona("experienced software engineer", "comprehensive code review") .task_context("Thorough code review focusing on quality and best practices") .core_analysis([ "Code correctness and logic", "Performance and efficiency", "Security considerations", "Maintainability and readability", "Test coverage and edge cases" ]) .output_format([ "## Summary: Overall assessment and key points", "## Issues: Specific problems with line references", "## Suggestions: Concrete improvement recommendations", "## Strengths: What the code does well" ]) .final_emphasis("Constructive feedback that helps developers improve") ._build() ) # Use the same template across different team contexts senior_reviewer = tb.ChatBot().model("gpt-4-turbo").system_prompt(code_review_template) junior_reviewer = tb.ChatBot().model("gpt-3.5-turbo").system_prompt(code_review_template) # Customize for specific languages while keeping base structure python_template = ( tb.PromptBuilder() .from_template(code_review_template) # Inherit base structure .add_constraint("Focus on Pythonic idioms and PEP 8 compliance") ._build() ) python_reviewer = tb.ChatBot().model("gpt-4-turbo").system_prompt(python_template) ``` **When to use each approach:** - **Direct String**: simple, one-off prompts - **ChatBot.prompt_builder()**: complex prompts for single bot instance - **PromptBuilder Class**: reusable templates, team standards, prompt libraries Best Practices -------------- **Use direct strings for simple prompts**: quick, straightforward prompts work well with direct string assignment when you need something fast and simple. **Use `ChatBot.prompt_builder()` for complex single-use prompts**: when creating sophisticated system prompts for a specific ChatBot instance with multiple sections, constraints, and formatting requirements. **Use `PromptBuilder` class directly for reusable templates**: when you need prompt templates that can be shared across multiple ChatBot instances, team standards, or organizational prompt libraries. **Combine with other methods**: all three approaches work seamlessly with `.persona()`, `.avoid()`, and other configuration methods for additional customization. **Template Hierarchy**: consider creating base templates with PromptBuilder class and extending them for specific use cases to maintain consistency while allowing customization. Notes ----- **Attention Optimization**: both `PromptBuilder` approaches create prompts that follow modern prompt engineering research on attention patterns and cognitive load optimization. **Maintenance**: structured prompts created with `PromptBuilder` are easier to modify, debug, and version control in team environments. **Performance**: all three approaches result in equivalent runtime performance; the choice is primarily about development experience, maintainability, and reusability needs. See Also -------- prompt_builder : Create attention-optimized structured prompts from ChatBot instances PromptBuilder : The `PromptBuilder` class for reusable prompt templates and team standards persona : Add personality context that complements system prompts preset : Use pre-configured system prompts for common use cases avoid : Add constraints that work with any system prompt approach get_system_prompt(self) -> str Get the final constructed system prompt that will be sent to the LLM. This combines preset system prompts, custom system prompts, persona descriptions, constraints from 'avoid' settings, and other configuration elements into the final prompt text. Returns ------- str The complete system prompt that will be used for LLM interactions Examples -------- >>> bot = ChatBot().preset("technical_advisor").persona("Senior Engineer") >>> print(bot.get_system_prompt()) "You are a senior technical advisor..." avoid(self, avoid_list: list[str]) -> 'ChatBot' Configure topics or behaviors the chatbot must refuse to engage with. The avoid list feeds into both the system prompt (instructing the LLM to decline requests on these topics) and the `autotest_avoid_topics()` testing framework that validates compliance. Parameters ---------- avoid_list A list of topic strings the chatbot should not discuss or assist with (e.g., `["medical_advice", "legal_advice"]`). Returns ------- ChatBot The same instance for method chaining. Examples -------- ```{python} import talk_box as tb bot = tb.ChatBot().avoid(["medical_advice", "financial_planning"]) bot.get_avoid_topics() ``` get_avoid_topics(self) -> list[str] Get the list of topics or behaviors this chatbot is configured to avoid. This method provides access to the original avoid topics configuration, which is essential for testing frameworks that need to validate whether the bot properly adheres to its avoid topics constraints. Returns ------- list[str] A copy of the avoid topics list to prevent external modification Examples -------- >>> bot = ChatBot().avoid(["medical_advice", "financial_planning"]) >>> topics = bot.get_avoid_topics() >>> print(topics) ['medical_advice', 'financial_planning'] tools(self, tools: Union[list[str], list['TalkBoxTool'], str]) -> 'ChatBot' Configure tools for this chatbot with unified API for custom and built-in tools. This method provides a single, consistent way to add any combination of: - Built-in Tool Box tools (by string name) - Custom tools (by passing TalkBoxTool objects) - Tools from Python files (by file/directory path) - All Tool Box tools (with "all" shortcut) Parameters ---------- tools : Union[list[str], list[TalkBoxTool], str] Tools to add to this chatbot. Can be: - List of string names for built-in Tool Box tools: ["calculate", "web_search"] - List of TalkBoxTool objects for custom tools: [my_custom_tool, another_tool] - Mixed list: ["calculate", my_custom_tool, "web_search", "my_tools.py"] - String "all" to load all built-in Tool Box tools - Python file path: "my_tools.py" to load all tools from file - Directory path: "./tools/" to load all tools from directory Returns ------- ChatBot The chatbot instance with tools configured for method chaining Examples -------- >>> # Add specific built-in tools >>> bot = ChatBot().tools(["calculate", "text_stats", "validate_email"]) >>> # Add custom tools >>> bot = ChatBot().tools([my_custom_tool, another_custom_tool]) >>> # Mix built-in and custom tools >>> bot = ChatBot().tools(["calculate", my_custom_tool, "web_search"]) >>> # Load all built-in tools >>> bot = ChatBot().tools("all") >>> # Load tools from Python file >>> bot = ChatBot().tools("my_business_tools.py") >>> # Load tools from directory >>> bot = ChatBot().tools("./company_tools/") >>> # Mix file loading with other tools >>> bot = ChatBot().tools(["calculate", "my_tools.py", my_custom_tool]) >>> # Chaining - add more tools later >>> bot = ChatBot().tools(["calculate"]).tools([my_custom_tool]) add_tools(self, tool_names: list[str]) -> 'ChatBot' Add specific built-in tools. Parameters ---------- tool_names : list[str] Names of specific Tool Box tools to add Returns ------- ChatBot The chatbot instance with selected tools for method chaining Examples -------- >>> bot = ChatBot().add_tools(["calculate", "text_stats"]) verbose(self, enabled: bool = True) -> 'ChatBot' Enable or disable verbose diagnostic output during chat interactions. When verbose mode is active the chatbot prints additional diagnostic information (e.g., prompt construction details, model parameters) to stdout during each call to `chat()` or `show()`. Parameters ---------- enabled Set to `True` to turn on verbose output, `False` to silence it. Defaults to `True`. Returns ------- ChatBot The same instance for method chaining. Examples -------- ```{python} import talk_box as tb bot = tb.ChatBot().verbose() bot.get_config()["verbose"] ``` chat(self, message: Union[str, ForwardRef('Attachments')], conversation: Optional[ForwardRef('Conversation')] = None) -> 'Conversation' Send a message to the chatbot and get a response within a conversation context. This method creates or updates a conversation by adding the user's message and the chatbot's response. If no conversation is provided, a new one is automatically created. This is the primary way to interact with the chatbot while maintaining conversation history and context. Parameters ---------- message The user's message to send to the chatbot. Can be: - A string message - An Attachments object containing files and an optional prompt conversation An existing conversation to continue. If not provided, a new conversation is created automatically. Returns ------- Conversation The conversation object containing the full message history including the new user message and chatbot response. Examples -------- ### Basic single-message chat ```python import talk_box as tb bot = tb.ChatBot().model("gpt-4").temperature(0.7) convo = bot.chat("Hello! How are you?") print(convo.get_last_message().content) ``` ### Chat with file attachments ```python from talk_box import ChatBot from talk_box.attachments import Attachments bot = ChatBot().model("gpt-4") # Create attachments attachments = Attachments().with_prompt("What's in these files?") attachments.add_file("document.pdf") attachments.add_file("image.png") # Chat with attachments convo = bot.chat(attachments) print(convo.get_last_message().content) ``` ### Continuing a conversation ```python # Start a conversation convo = bot.chat("What's machine learning?") # Continue the same conversation convo = bot.chat("Can you give me an example?", conversation=convo) # View full conversation history for msg in convo.get_messages(): print(f"{msg.role}: {msg.content}") ``` start_conversation(self) -> 'Conversation' Start a new conversation with this chatbot. Creates a fresh conversation instance that can be used for multi-turn interactions with the chatbot. This is useful when you want to explicitly manage conversation state and context. Returns ------- Conversation A new, empty conversation instance ready for interaction. Examples -------- ### Starting a managed conversation ```python import talk_box as tb # Configure chatbot bot = tb.ChatBot().model("gpt-4").temperature(0.7).preset("helpful") # Start a new conversation conversation = bot.start_conversation() # Add messages manually or use chat method conversation.add_user_message("Hello!") updated_conversation = bot.chat("How are you?", conversation=conversation) ``` continue_conversation(self, conversation: 'Conversation', message: str) -> 'Conversation' Continue an existing conversation with a new message. This is a convenience method that's equivalent to calling `chat(message, conversation=conversation)` but makes the intent of continuing a conversation more explicit. Parameters ---------- conversation The existing conversation to continue. message The user's message to add to the conversation. Returns ------- Conversation The updated conversation with the new exchange. Examples -------- ```python # Start conversation conversation = bot.start_conversation() # Continue it explicitly conversation = bot.continue_conversation(conversation, "What's the weather like?") conversation = bot.continue_conversation(conversation, "What about tomorrow?") ``` show(self, mode: str = 'help') -> None Display diagnostic information or launch chat interfaces. This method provides explicit control over displaying diagnostic information and launching chat interfaces, complementing the automatic display when the ChatBot object is shown. Parameters ---------- mode The type of interface to show: - `"browser"`: launch browser chat interface - `"console"`: launch interactive console/terminal chat - `"config"`: display configuration summary in notebook - `"prompt"`: display the final system prompt - `"help"`: show quick-start guide for using this ChatBot - `"status"`: check LLM integration status and troubleshooting - `"install"`: show step-by-step chatlas installation guide Examples -------- >>> bot = ChatBot().model("gpt-4").preset("technical_advisor") >>> bot.show("help") # Show quick-start guide (default) >>> bot.show("status") # Check LLM integration status >>> bot.show("browser") # Launch browser chat interface >>> bot.show("console") # Launch terminal chat interface >>> bot.show("config") # Show configuration summary get_config_summary(self) -> dict[str, typing.Any] Get a comprehensive summary of the current chatbot configuration. This includes model settings, prompt configuration, and metadata: useful for debugging, logging, A/B testing, and displaying in UI components. Returns ------- dict[str, Any] Complete configuration summary including: - basic info (name, description, id) - model parameters (model, temperature, max_tokens) - prompt components (preset, custom prompt, persona, constraints) - system prompt (final constructed prompt) - advanced settings (tools, verbose mode, LLM status) Examples -------- >>> bot = ChatBot(name="Support Bot").preset("customer_support") >>> config = bot.get_config_summary() >>> print(config["name"], config["model"], len(config["system_prompt"])) "Support Bot" "gpt-3.5-turbo" 245 get_config(self) -> dict[str, typing.Any] Return a copy of the full chatbot configuration dictionary. The returned dictionary includes all settings applied through the fluent API (model, temperature, persona, tools, etc.). Because it is a shallow copy, mutations do not affect the chatbot's internal state. Returns ------- dict[str, Any] A copy of the configuration dictionary with keys such as `"model"`, `"temperature"`, `"persona"`, `"tools"`, `"verbose"`, and others. Examples -------- ```{python} import talk_box as tb bot = tb.ChatBot().model("gpt-4").temperature(0.2) config = bot.get_config() print(config["model"], config["temperature"]) ``` prompt_builder(self, builder_type: Union[str, ForwardRef('BuilderTypes')] = 'general') -> 'PromptBuilder' Create an attention-optimized prompt builder for declarative prompt composition. This method returns a specialized prompt builder that implements attention-based structuring principles from modern prompt engineering research. The builder helps engineers create prompts with optimal attention patterns through a fluent, declarative API. Based on research showing that structure matters more than specific word choices, this builder enables you to: - front-load critical information (primacy bias) - create structured sections for clear attention clustering - avoid attention drift through specific constraints - build modular, maintainable prompt components Parameters ---------- builder_type Type of prompt builder to create. You can use either a string or a constant from `BuilderTypes` for better autocomplete and type safety. Returns ------- PromptBuilder A prompt builder with methods for declarative prompt composition. Available builder types ----------------------- The following builder types are available: - `BuilderTypes.GENERAL` or `"general"`: basic attention-optimized builder - `BuilderTypes.ARCHITECTURAL` or `"architectural"`: pre-configured for code architecture analysis - `BuilderTypes.CODE_REVIEW` or `"code_review"`: pre-configured for code review tasks - `BuilderTypes.DEBUGGING` or `"debugging"`: pre-configured for debugging assistance Examples -------- ### Basic attention-optimized prompt building ```python import talk_box as tb bot = tb.ChatBot().model("gpt-4-turbo") # Build an attention-optimized prompt prompt = (bot.prompt_builder() .persona("senior software architect", "comprehensive codebase analysis") .task_context("Create architectural documentation") .critical_constraint("Focus on identifying architectural debt") .core_analysis([ "Tools, frameworks, and design patterns", "Data models and API design patterns", "Architectural inconsistencies" ]) .output_format([ "Use clear headings and bullet points", "Include specific examples from codebase" ]) .final_emphasis("Prioritize findings by impact and consistency") .build()) # Use the structured prompt response = bot.chat(prompt) ``` ### Pre-configured builders for common tasks ```python # Architectural analysis with pre-configured structure arch_prompt = (bot.prompt_builder(tb.BuilderTypes.ARCHITECTURAL) .focus_on("identifying technical debt") .build()) # Code review with attention-optimized structure review_prompt = (bot.prompt_builder(tb.BuilderTypes.CODE_REVIEW) .avoid_topics(["personal criticism"]) .focus_on("actionable improvement suggestions") .build()) ``` ### Preview prompt structure before building ```python builder = (bot.prompt_builder() .persona("technical advisor") .core_analysis(["Security", "Performance", "Maintainability"]) .output_format(["Structured sections", "Specific examples"])) # Preview the attention structure structure = builder.preview_structure() print(f"Estimated tokens: {structure['estimated_tokens']}") print(f"Priority sections: {len(structure['structured_sections'])}") # Build when satisfied with structure prompt = builder._build() ``` Notes ----- The returned builder implements attention-based principles: - **Primacy bias**: critical information is front-loaded - **Structured sections**: clear attention clustering prevents drift - **Personas**: behavioral anchoring for consistent responses - **Specific constraints**: avoid vague instructions that cause attention drift - **Recency bias**: final emphasis leverages end-of-prompt attention See Also -------- PromptBuilder : The full prompt builder API preset : Use presets for quick specialized configurations persona : Set behavioral context for responses structured_prompt(self, **sections) -> 'ChatBot' Configure the chatbot with a structured prompt built from keyword sections. This is a convenience method for quickly building attention-optimized prompts without using the full prompt builder API. It automatically structures the provided sections according to attention-based principles. Parameters ---------- **sections Keyword arguments defining prompt sections. Returns ------- ChatBot Returns self for method chaining Recognized Keyword Arguments ----------------------------- - `persona`: behavioral role (e.g., `"senior developer"`) - `task`: primary task description - `constraints`: list of requirements or constraints - `format`: list of output formatting requirements - `examples`: dict of input/output examples - `focus`: primary goal to emphasize Examples -------- ### Quick structured prompt creation ```python import talk_box as tb bot = ( tb.ChatBot() .model("gpt-4-turbo") .structured_prompt( persona="senior software architect", task="Analyze codebase architecture and identify improvements", constraints=[ "Focus on security vulnerabilities", "Identify performance bottlenecks", "Suggest specific fixes" ], format=[ "Use bullet points for findings", "Include code examples", "Prioritize by severity" ], focus="actionable recommendations for immediate implementation" ) ) ``` ### Combining with other configuration ```python expert_bot = ( tb.ChatBot() .model("gpt-4-turbo") .temperature(0.2) .structured_prompt( persona="expert debugger", task="Identify root cause of performance issues", constraints=["Provide reproducible test cases"], focus="finding the root cause, not just symptoms" ) .max_tokens(1500) ) ``` chain_prompts(self, *prompts) -> 'ChatBot' Chain multiple structured prompts in attention-optimized order. This method allows you to combine multiple prompt components while maintaining optimal attention patterns. Components are automatically ordered to maximize the model's focus on the most important information. Parameters ---------- *prompts Prompt components to chain together. Can be raw strings or `PromptBuilder` instances. Returns ------- ChatBot Returns self for method chaining. Examples -------- ### Chaining different prompt components ```python # Create specialized prompt components security_prompt = (bot.prompt_builder() .core_analysis(["SQL injection risks", "XSS vulnerabilities"]) .build()) performance_prompt = (bot.prompt_builder() .core_analysis(["Database query optimization", "Memory usage"]) .build()) # Chain them with attention optimization bot.chain_prompts( "You are a senior security and performance engineer.", security_prompt, performance_prompt, "Focus on the most critical issues that impact user security." ) ``` check_llm_status(self) -> dict Check the status of LLM integration and get setup help if needed. Returns a dictionary indicating whether the LLM backend is active, the current status string, and a help payload with troubleshooting guidance when the integration is not enabled. Returns ------- dict A dictionary with the following keys: - `"enabled"` (bool): Whether the LLM is active. - `"status"` (str): Human-readable status label. - `"help"` (str | dict): Setup instructions or confirmation message. Examples -------- ```{python} import talk_box as tb bot = tb.ChatBot() status = bot.check_llm_status() status["enabled"] ``` quick_start(self) -> str Get a quick-start guide tailored to this chatbot's current configuration. The guide covers basic usage commands, configuration options, and the chatbot's active settings (model, temperature, etc.). Returns ------- str A multi-line guide string ready to print. Examples -------- ```{python} import talk_box as tb bot = tb.ChatBot().model("gpt-4") guide = bot.quick_start() "gpt-4" in guide ``` create_chat_session(self) Create a chat session backed by the configured LLM provider. When *chatlas* is installed this returns a fully configured `chatlas.Chat` instance ready for interactive use. If chatlas is unavailable a lightweight `SimpleChatSession` fallback is returned instead. Returns ------- chatlas.Chat | SimpleChatSession A chat session object. The concrete type depends on whether the chatlas package is installed. Examples -------- ```python import talk_box as tb bot = tb.ChatBot().model("gpt-4") session = bot.create_chat_session() ``` ## Prompt Engineering Attention-optimized prompt construction PromptBuilder() Builds structured prompts using attention mechanisms and cognitive principles. The `PromptBuilder` leverages insights from modern prompt engineering research to create prompts that maximize model attention on critical information while maintaining natural conversation flow. Returns ------- PromptBuilder A new instance ready for fluent method chaining Notes ----- The `PromptBuilder` applies proven principles that enhance model performance and response quality through strategic information placement and cognitive load management. **Attention Mechanisms Applied:** - **Positional encoding**: critical information placed strategically - **Multi-head attention**: different types of context handled separately - **Hierarchical structure**: information organized by importance and relevance - **Context windowing**: optimal information density for model processing **Cognitive Psychology Integration:** - **Primacy effect**: important instructions placed early - **Recency effect**: final emphasis reinforces key objectives - **Chunking**: information grouped into digestible, logical units - **Salience**: critical constraints highlighted for maximum attention **Prompt Building Methods** The `PromptBuilder` provides a comprehensive set of methods for creating structured, attention-optimized prompts. All methods support fluent chaining for natural prompt construction. The core foundation methods: - `persona(role, expertise=None)`: set the AI's identity and behavioral framework - `task_context(context, priority=CRITICAL)`: define the primary objective and scope - `critical_constraint(constraint)`: add front-loaded, non-negotiable requirements - `constraint(constraint)`: add important but secondary requirements The structure and analysis methods: - `structured_section(title, content, priority=MEDIUM, required=False)`: create organized content sections - `core_analysis(analysis_points)`: define required analytical focus areas - `output_format(format_specs)`: specify response structure and formatting requirements - `example(input_example, output_example)`: provide concrete input/output demonstrations The focus and guidance methods: - `focus_on(primary_goal)`: emphasize the most important objective - `avoid_topics(topics)`: explicitly exclude irrelevant or problematic areas - `final_emphasis(emphasis)`: add closing reinforcement using recency bias Output methods: - `build()`: generate the final structured prompt string - `preview_structure()`: preview the prompt organization and metadata Each method is designed to work together in the attention-optimized prompt structure, with positioning and formatting automatically handled to maximize model performance. Examples -------- ### Basic prompt construction Create a simple prompt with persona and task: ```python import talk_box as tb prompt = ( tb.PromptBuilder() .persona("data scientist", "machine learning") .task_context("analyze customer churn patterns") .focus_on("identifying the top 3 risk factors") ) ``` We can easily print the prompt that was generated for this task: ```python print(prompt) ``` ### Structured analysis prompt It is possible to build a much more comprehensive analysis prompt with multiple sections: ```python prompt = ( tb.PromptBuilder() .persona("senior software architect") .critical_constraint("focus only on production-ready solutions") .task_context("review the codebase architecture") .core_analysis([ "identify design patterns used", "assess scalability bottlenecks", "review security implications" ]) .structured_section( "Performance Metrics", [ "response time requirements", "throughput expectations", "memory usage constraints" ], priority=tb.Priority.HIGH ) .output_format([ "executive summary (2-3 sentences)", "detailed findings with code examples", "prioritized recommendations" ]) .final_emphasis("provide actionable next steps") ) ``` The generated prompt can be printed as follows: ```python print(prompt) ``` ### Code review prompt Create a specialized prompt for code reviews: ```python prompt = ( tb.PromptBuilder() .persona("senior developer", "code quality and best practices") .task_context("review the pull request for potential issues") .critical_constraint("flag any security vulnerabilities immediately") .structured_section( "Review Areas", [ "logic and correctness", "security considerations", "performance implications", "code readability and documentation" ] ) .output_format([ "critical issues (must fix)", "suggestions (should consider)", "positive feedback" ]) .avoid_topics(["personal coding style preferences"]) .focus_on("providing constructive, actionable feedback") ) ``` We can look at the generated prompt: ```python print(prompt) ``` persona(self, role: str, expertise: Optional[str] = None) -> 'PromptBuilder' Set a behavioral persona to anchor the model's response style and establish expertise context. The persona method establishes the AI's identity and behavioral framework, which serves as the foundation for all subsequent interactions. This method leverages behavioral psychology principles to create consistent, expert-level responses aligned with the specified role and domain expertise. Parameters ---------- role The primary professional role or identity the AI should adopt. This should be specific and professional (e.g., `"senior software architect"`, `"data scientist"`, `"technical writer"`, etc.). The role influences response style, terminology, and the level of technical depth provided. expertise Specific area of expertise or specialization within the role. This narrows the focus and enhances domain-specific knowledge application (e.g., `"distributed systems"`, `"machine learning"`, `"API documentation"`, etc.). If not provided, the persona will be general within the specified role. Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Behavioral Psychology.** Persona establishment leverages behavioral psychology principles to create consistent response patterns aligned with professional roles and expertise domains. **Identity Anchoring.** Setting a clear professional identity serves as a cognitive anchor that influences all subsequent AI reasoning and response generation processes. **Domain Expertise Activation.** Specifying expertise areas activates relevant knowledge domains and professional terminology appropriate to the specified field. Prompt Positioning ------------------ Persona statements are positioned at the very beginning of prompts to establish the behavioral framework before any task instructions or constraints are provided. Best Practices -------------- Follow these guidelines for effective persona establishment: - use specific, professional role titles rather than generic descriptions - include relevant expertise areas to enhance domain-specific knowledge application - ensure persona aligns with the complexity and scope of the intended task - maintain consistency with persona throughout all prompt elements Integration Notes ----------------- - **Behavioral Anchoring**: the persona establishes cognitive framework before task instructions - **Response Consistency**: maintains consistent voice and expertise level throughout interaction - **Domain Knowledge**: activates relevant knowledge domains and professional terminology - **Communication Style**: influences formality, technical depth, and explanatory approach - **Quality Indicators**: expert personas tend to provide more nuanced, comprehensive responses The `.persona()` method provides the foundational identity that guides all subsequent AI behavior, ensuring responses align with professional expectations and domain expertise requirements. Examples -------- ### Basic role assignment Set a clear professional identity for the AI: ```python import talk_box as tb # Simple role without specific expertise builder = ( tb.PromptBuilder() .persona("data analyst") .task_context("analyze customer satisfaction survey results") ) print(builder) ``` ### Role with domain expertise Combine role with specific area of expertise: ```python # Specialized expertise within role builder = ( tb.PromptBuilder() .persona("software engineer", "backend API development") .task_context("review the authentication service architecture") .core_analysis([ "security implementation patterns", "scalability considerations", "error handling strategies" ]) ) print(builder) ``` ### Senior-level expertise Use seniority indicators for complex tasks: ```python # Senior-level role for complex analysis builder = ( tb.PromptBuilder() .persona("senior software architect", "distributed systems") .critical_constraint("focus on production-scale considerations") .task_context("design a microservices architecture for high-traffic e-commerce") ) ``` ### Domain-specific personas We can create personas tailored to specific industries or domains. Here is one that is focused on healthcare domain expertise: ```python healthcare_builder = ( tb.PromptBuilder() .persona("healthcare data analyst", "clinical research") .task_context("analyze patient outcome data for treatment effectiveness") ) print(healthcare_builder) ``` This is a specialized persona for the financial services industry: ```python finance_builder = ( tb.PromptBuilder() .persona("quantitative analyst", "risk management") .task_context("evaluate portfolio risk exposure across asset classes") ) print(finance_builder) ``` This is a persona with educational technology expertise: ```python edtech_builder = ( tb.PromptBuilder() .persona("educational technologist", "learning analytics") .task_context("design metrics for measuring student engagement") ) print(edtech_builder) ``` ### Combining personas with other prompt elements Build comprehensive prompts with persona as the foundation: ```python # Complete code review prompt with expert persona review_prompt = ( tb.PromptBuilder() .persona("senior code reviewer", "security and performance") .critical_constraint("prioritize security vulnerabilities over style issues") .task_context("review this Python Flask application for production readiness") .core_analysis([ "authentication and authorization implementation", "input validation and sanitization", "database query optimization", "error handling and logging" ]) .output_format([ "critical security issues (immediate attention)", "performance bottlenecks (optimization opportunities)", "code quality improvements (maintainability)", "positive patterns (reinforcement)" ]) .final_emphasis("focus on issues that could impact production security or performance") ) print(review_prompt) ``` ### Persona influence on response style Subtle differences in personas can affect response characteristics: ```python # Technical depth variation beginner_persona = ( tb.PromptBuilder() .persona("junior developer") .task_context("explain RESTful API design principles") ) print(beginner_persona) ``` ```python expert_persona = ( tb.PromptBuilder() .persona("principal engineer", "API architecture") .task_context("explain RESTful API design principles") ) print(expert_persona) ``` The expert persona will provide more sophisticated insights, advanced patterns, and industry best practices compared to the junior developer persona's more fundamental explanations. ### Multiple expertise areas We can handle roles with multiple specializations. This persona has broad expertise combining multiple areas. ```python fullstack_persona = ( tb.PromptBuilder() .persona("full-stack architect", "web applications and cloud infrastructure") .task_context("design end-to-end solution for real-time collaboration platform") ) print(fullstack_persona) ``` This is a research-focused persona with interdisciplinary expertise. ```python research_persona = ( tb.PromptBuilder() .persona("research scientist", "machine learning and cognitive psychology") .task_context("evaluate AI model bias in human-computer interaction contexts") ) print(research_persona) ``` ### Persona consistency across conversations Maintain consistent persona behavior in extended interactions: ```python # Establish consistent technical writing persona technical_writer = ( tb.PromptBuilder() .persona("technical documentation specialist", "developer tools") .task_context("create user guide for API integration") ) print(technical_writer) ``` task_context(self, context: str, priority: talk_box.prompt_builder.Priority = ) -> 'PromptBuilder' Define the primary task context that establishes what needs to be accomplished. The task context serves as the central objective that guides the entire prompt. It appears prominently in the final prompt structure and provides clear direction for the AI model. This method is essential for creating focused, goal-oriented prompts that produce relevant and actionable responses. Parameters ---------- context Clear, specific description of what needs to be accomplished. Should be action-oriented and provide sufficient detail for the AI to understand the expected scope and deliverables. priority Attention priority level for task placement in the final prompt. Defaults to `Priority.CRITICAL` to ensure the main task receives prominent positioning and maximum attention. Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods. Prompt Positioning ------------------ Task context is typically placed early in the prompt structure (after persona and critical constraints) to establish clear expectations. The default `CRITICAL` priority ensures the task receives prominent attention placement. Best Practices -------------- Follow these guidelines for effective task definition: - use clear, specific language that defines measurable outcomes - focus on action-oriented descriptions ("analyze", "review", "create") - avoid vague or ambiguous task descriptions - include scope boundaries when appropriate Examples -------- ### Basic task definition Set a clear, focused task for the prompt: ```python import talk_box as tb # Simple task context builder = ( tb.PromptBuilder() .persona("data analyst") .task_context("analyze the customer churn data to identify key patterns") ) print(builder) ``` ### Task with custom priority Use different priority levels for task positioning. Here is an example of a high priority task that is important but not critical: ```python builder = ( tb.PromptBuilder() .persona("software architect") .critical_constraint("focus only on security vulnerabilities") .task_context( "review the authentication system architecture", priority=tb.Priority.HIGH ) ) print(builder) ``` ### Detailed task with scope boundaries Create comprehensive task descriptions with clear boundaries: ```python # Detailed task with specific scope builder = ( tb.PromptBuilder() .persona("technical writer", "API documentation") .task_context( "create comprehensive API documentation for the user management endpoints, " "including authentication requirements, request/response examples, " "and error handling procedures" ) .core_analysis([ "document each endpoint's purpose and functionality", "provide complete request/response schemas", "include practical usage examples" ]) ) print(builder) ``` focus_on(self, primary_goal: str) -> 'PromptBuilder' Set the primary focus that leverages both front-loading and recency bias for maximum attention impact. `.focus_on()` provides a powerful dual-positioning method that ensures the most critical objective receives maximum attention throughout the prompt by strategically placing it both at the beginning (as a critical constraint) and at the end (as final emphasis). This dual-anchor approach leverages both primacy and recency effects to create the strongest possible attention focus on the primary objective. Parameters ---------- primary_goal The single most important objective that must receive maximum attention and priority throughout the AI's response. Should be formulated as a clear, specific, and measurable objective that captures the essential purpose of the prompt (e.g., `"provide actionable security recommendations"`, `"create implementable cost reduction strategies"`, `"generate learning-focused technical explanations"`, etc.). Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------ **Dual Attention Strategy.** Information positioned at both the beginning and end of a sequence receives the highest attention and retention. By anchoring the primary goal at both positions, `.focus_on()` ensures that the most critical objective maintains prominence throughout the entire prompt processing sequence. **Primacy and Recency Effects.** The method capitalizes on both primacy bias (heightened attention to early information) and recency bias (heightened attention to final information) to create a reinforcing attention pattern that keeps the primary objective at the forefront of the AI's processing throughout response generation. **Objective Reinforcement.** Unlike single-position emphasis methods, `.focus_on()` creates a reinforcing loop where the primary goal is established early as a critical requirement and then reinforced at the end as the ultimate focus. This dual reinforcement significantly reduces the risk of objective drift in complex prompts. **Attention Hierarchy Management.** By explicitly establishing one primary objective above all others, this method helps manage attention hierarchy in complex prompts with multiple competing requirements, ensuring that when trade-offs must be made, the primary goal takes clear precedence. Integration Notes ----------------- - **Dual Positioning**: leverages both primacy and recency effects for maximum attention impact - **Objective Reinforcement**: creates reinforcing attention pattern that prevents goal drift - **Attention Hierarchy**: establishes clear priority structure for complex prompts - **Trade-off Guidance**: provides clear decision criteria when competing objectives conflict - **Quality Assurance**: ensures responses align with the most critical objective throughout - **Strategic Emphasis**: combines front-loaded critical constraints with end-positioned final emphasis The `.focus_on()` method provides the strongest possible attention management by establishing the primary objective as both the opening critical requirement and closing final emphasis, creating a dual-anchor system that maintains unwavering focus on the most important goal throughout the entire AI response generation process. Examples -------- ### Security-first system analysis Ensure security remains the absolute priority across all considerations: ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("security architect", "enterprise security design") .focus_on("identify and eliminate all security vulnerabilities before considering any other improvements") .task_context("analyze enterprise application architecture for production deployment") .core_analysis([ "authentication and authorization mechanisms", "data protection and encryption standards", "network security and access controls", "infrastructure security configuration" ]) .constraint("include performance optimization suggestions where security-compatible") .constraint("consider user experience implications of security measures") .output_format([ "security assessment with risk severity levels", "critical vulnerabilities requiring immediate attention", "security-first recommendations with implementation priorities" ]) ) print(builder) ``` ### Cost-effectiveness priority Prioritize cost-effective solutions above all other considerations: ```python builder = ( tb.PromptBuilder() .persona("operations consultant", "cost optimization and efficiency") .focus_on("maximize cost savings while maintaining operational quality") .task_context("develop operational efficiency improvement plan for manufacturing company") .core_analysis([ "current cost structure and inefficiencies", "automation and technology opportunities", "process optimization potential", "resource allocation improvements" ]) .constraint("include innovation opportunities where cost-effective") .constraint("consider employee impact and change management") .output_format([ "cost analysis with savings potential", "implementation priorities by ROI and payback period", "budget-conscious recommendations with measurable outcomes" ]) ) print(builder) ``` ### User experience excellence Make user experience the paramount consideration in all decisions: ```python builder = ( tb.PromptBuilder() .persona("UX designer", "user-centered product design") .focus_on("optimize every aspect of the user experience above technical or business convenience") .task_context("redesign mobile banking application interface for improved usability") .core_analysis([ "user journey mapping and pain points", "accessibility and inclusive design requirements", "interface clarity and intuitive navigation", "performance impact on user experience" ]) .constraint("consider technical implementation constraints") .constraint("include business stakeholder requirements") .output_format([ "UX assessment with user impact analysis", "design recommendations prioritized by user value", "implementation plan with user testing validation" ]) ) print(builder) ``` ### Learning-centered education Prioritize learning effectiveness over all other educational considerations: ```python builder = ( tb.PromptBuilder() .persona("instructional designer", "evidence-based learning design") .focus_on("maximize student learning outcomes and knowledge retention") .task_context("design comprehensive data science curriculum for career changers") .core_analysis([ "learning objective alignment and progression", "skill building sequence and scaffolding", "practice opportunities and feedback mechanisms", "real-world application and project integration" ]) .constraint("consider time constraints and resource limitations") .constraint("include diverse learning styles and accessibility") .output_format([ "curriculum structure with learning outcome mapping", "module design with skill progression tracking", "assessment strategy focused on competency development" ]) ) print(builder) ``` ### Compliance-first approach Ensure regulatory compliance takes absolute precedence: ```python builder = ( tb.PromptBuilder() .persona("compliance officer", "financial services regulation") .focus_on("ensure 100% regulatory compliance before any operational considerations") .task_context("audit investment management platform for regulatory adherence") .core_analysis([ "regulatory requirement mapping and gaps", "risk assessment and mitigation strategies", "documentation and audit trail completeness", "process compliance and control effectiveness" ]) .constraint("include operational efficiency opportunities where compliant") .constraint("consider user experience impact of compliance measures") .output_format([ "compliance status with regulatory requirement tracking", "critical violations requiring immediate remediation", "compliance-first recommendations with implementation priorities" ]) ) print(builder) ``` ### Innovation-driven development Prioritize innovative solutions that provide competitive advantage: ```python builder = ( tb.PromptBuilder() .persona("innovation strategist", "emerging technology adoption") .focus_on("identify and implement innovative solutions that create significant competitive advantage") .task_context("develop technology roadmap for digital transformation initiative") .core_analysis([ "emerging technology opportunities and applications", "competitive differentiation potential", "implementation feasibility and risk assessment", "ROI and business impact projections" ]) .constraint("consider enterprise stability and risk tolerance") .constraint("include team capability development requirements") .output_format([ "innovation assessment with competitive impact analysis", "technology recommendations prioritized by advantage potential", "implementation strategy with innovation milestones" ]) ) print(builder) ``` ### Quality-first manufacturing Make product quality the overriding priority in all manufacturing decisions: ```python builder = ( tb.PromptBuilder() .persona("quality engineer", "manufacturing excellence") .focus_on("achieving superior product quality that exceeds customer expectations") .task_context("optimize manufacturing process for automotive component production") .core_analysis([ "current quality metrics and defect analysis", "process control and variability reduction", "quality assurance and testing protocols", "continuous improvement opportunities" ]) .constraint("consider production efficiency where quality-compatible") .constraint("include cost implications of quality improvements") .output_format([ "quality assessment with defect root cause analysis", "process improvements prioritized by quality impact", "implementation plan with quality validation metrics" ]) ) print(builder) ``` critical_constraint(self, constraint: str) -> 'PromptBuilder' Add a critical constraint that will be front-loaded for maximum attention and impact. Critical constraints are the highest-priority requirements that must be prominently positioned in the final prompt to ensure maximum model attention and compliance. These constraints are automatically placed in the `"CRITICAL REQUIREMENTS"` section immediately after the persona and before the main task, leveraging the primacy effect to maximize their influence on response generation. Parameters ---------- constraint Specific constraint or requirement that must receive maximum attention. Should be clear, actionable, and measurable when possible. Use imperative language for direct instruction (e.g., `"Focus only on security vulnerabilities"`, `"Provide exactly 3 recommendations"`, `"Avoid discussing implementation details"`, etc.). Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Primacy Effect Research.** Based on findings demonstrating that early-positioned instructions have the greatest impact on task accuracy and model compliance. The front-loading strategy ensures critical requirements receive maximum attention allocation during the model's processing phase. **Attention Positioning Theory.** Critical constraints are placed at the very beginning of the constraint hierarchy, appearing before any task context or analysis requirements. This strategic positioning leverages cognitive psychology principles where information presented early has disproportionate influence on decision-making and response generation. **Constraint Hierarchy Management.** Multiple critical constraints are ordered by insertion, with the first added appearing first in the final prompt. This allows for fine-grained control over the relative importance of multiple critical requirements, creating a clear precedence structure for complex prompts with competing priorities. **Use Case Classification.** Critical constraints are ideal for security and safety requirements that cannot be compromised, output format restrictions that must be strictly followed, behavioral boundaries that define acceptable response patterns, quality thresholds that determine response adequacy, and time-sensitive or high-stakes operational requirements. Integration Notes ----------------- - **Primacy Effect**: critical constraints appear early in the prompt for maximum impact - **Attention Allocation**: front-loading ensures these requirements receive priority processing - **Constraint Ordering**: multiple critical constraints maintain insertion order for hierarchical importance - **Quality Assurance**: critical constraints serve as quality gates for response evaluation - **Behavioral Anchoring**: works with persona to establish both identity and non-negotiable requirements The `.critical_constraint()` method ensures that the most important requirements are positioned for maximum attention and compliance, creating a foundation of non-negotiable standards that guide all subsequent reasoning and response generation. Examples -------- ### Security-focused critical constraint Prioritize security considerations above all else: ```python import talk_box as tb # Security-first code review builder = ( tb.PromptBuilder() .persona("senior security engineer", "application security") .critical_constraint("flag any security vulnerabilities immediately") .task_context("review this authentication implementation") .core_analysis([ "input validation and sanitization", "authentication mechanisms", "authorization controls" ]) ) print(builder) ``` ### Output format critical constraint Enforce strict output formatting requirements: ```python # Structured response requirement builder = ( tb.PromptBuilder() .persona("data analyst", "business intelligence") .critical_constraint("provide exactly 3 key findings with supporting data") .task_context("analyze quarterly sales performance") .output_format([ "Finding 1: [Insight] - [Supporting metric]", "Finding 2: [Insight] - [Supporting metric]", "Finding 3: [Insight] - [Supporting metric]" ]) ) print(builder) ``` ### Behavioral boundary critical constraint Set clear behavioral boundaries for sensitive topics: ```python # Medical advice boundary builder = ( tb.PromptBuilder() .persona("health information specialist") .critical_constraint( "do not provide specific medical diagnoses or treatment recommendations" ) .task_context( "explain general wellness concepts and direct to healthcare professionals" ) ) print(builder) ``` ### Quality threshold critical constraint Define minimum quality standards for responses: ```python # Production-ready focus builder = ( tb.PromptBuilder() .persona("senior software architect", "enterprise systems") .critical_constraint("focus only on production-ready, scalable solutions") .task_context("design microservices architecture for high-traffic application") .core_analysis([ "scalability patterns", "fault tolerance mechanisms", "performance optimization strategies" ]) ) print(builder) ``` ### Multiple critical constraints with hierarchy Layer multiple critical requirements in order of importance: ```python # Hierarchical critical constraints builder = ( tb.PromptBuilder() .persona("principal engineer", "financial systems") # First priority -- Regulatory compliance .critical_constraint("ensure all recommendations comply with financial regulations") # Second priority -- Proven solutions .critical_constraint("focus on solutions with proven track records in banking") # Third priority -- Security prioritization .critical_constraint("prioritize security over performance optimizations") .task_context("architect payment processing system for online banking") ) print(builder) ``` ### Time-sensitive critical constraint Handle urgent or time-critical requirements: ```python # Emergency response scenario builder = ( tb.PromptBuilder() .persona("incident response specialist", "system outages") .critical_constraint("provide immediate actionable steps for system recovery") .task_context("diagnose and resolve database connection failures") .output_format([ "immediate actions (next 5 minutes)", "short-term fixes (next hour)", "long-term prevention (next sprint)" ]) ) print(builder) ``` ### Domain-specific critical constraint Apply domain-specific requirements that cannot be compromised. In this example, we focus on healthcare data privacy: ```python builder = ( tb.PromptBuilder() .persona("healthcare data engineer", "HIPAA compliance") .critical_constraint("ensure all recommendations maintain patient data privacy") .task_context("design data pipeline for clinical research") ) print(builder) ``` ### Combining with other constraint types You can use critical constraints alongside standard constraints. Here, we combine two `.constraint()` calls with a front-loaded critical constraint: ```python # Comprehensive constraint strategy builder = ( tb.PromptBuilder() .persona("technical lead", "code quality") .task_context("review pull request for production release") .critical_constraint("identify blocking issues that prevent deployment") # Critical .constraint("consider coding style consistency") # Standard .constraint("suggest performance improvements") # Standard .core_analysis([ "security vulnerabilities", "logic errors and edge cases", "integration and compatibility issues" ]) ) print(builder) ``` constraint(self, constraint: str) -> 'PromptBuilder' Add a standard constraint to the prompt that will appear in the additional constraints section. Standard constraints are important requirements and guidelines that shape the AI's response but are not as critical as front-loaded constraints. These constraints appear in the `ADDITIONAL CONSTRAINTS` section after the main task context and structured sections, providing important guidance while maintaining the attention hierarchy of the prompt. Parameters ---------- constraint Specific constraint, requirement, or guideline that should influence the AI's response. Should be clear and actionable, using directive language when appropriate (e.g., `"Use clear, concise language"`, `"Include practical examples"`, `"Avoid overly technical jargon"`, etc.). Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Positioning Strategy Theory.** Standard constraints are positioned after critical constraints and core content to maintain optimal attention flow. This positioning ensures that essential task information receives primary focus while still communicating important requirements and preferences to the model. **Constraint Hierarchy Management.** Standard constraints appear in the order they are added, after any critical constraints. This allows for logical grouping of related requirements and systematic constraint organization that respects cognitive processing priorities. **Use Case Classification.** Standard constraints are ideal for quality preferences and style guidelines, secondary requirements that enhance output quality, behavioral preferences that improve response tone, technical preferences for implementation approaches, and context-specific guidelines that refine the response scope. **Differentiated Constraint Strategy.** While `critical_constraint()` is used for non-negotiable requirements that must be front-loaded, `constraint()` is used for important but secondary requirements that guide response quality and style without overriding primary attention allocation. Integration Notes ----------------- - **Attention Hierarchy**: standard constraints appear after critical content to maintain focus - **Quality Enhancement**: these constraints refine and improve response quality without overriding priorities - **Flexibility**: supports diverse requirement types from technical to behavioral to domain specific - **Systematic Organization**: constraints are grouped logically in the final prompt structure - **Complementary Function**: works alongside critical constraints to create comprehensive requirement sets The `.constraint()` method provides flexible, systematic way to communicate important requirements and preferences that enhance response quality while respecting the overall attention optimization strategy of the prompt building system. Examples -------- ### Quality and style constraints Add constraints that improve response quality and consistency: ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("technical writer", "API documentation") .task_context("create user guide for authentication API") .constraint("use clear, concise language appropriate for developers") .constraint("include practical code examples for each endpoint") .constraint("provide troubleshooting guidance for common issues") .core_analysis([ "authentication flow and requirements", "error handling and status codes", "rate limiting and best practices" ]) ) print(builder) ``` ### Technical preference constraints Guide implementation approaches and technical choices: ```python builder = ( tb.PromptBuilder() .persona("senior software architect", "microservices") .critical_constraint("focus only on production-ready patterns") .task_context("review microservices architecture design") .constraint("prefer established patterns over novel approaches") .constraint("consider scalability implications for each recommendation") .constraint("include performance trade-offs in analysis") .core_analysis([ "service decomposition strategy", "inter-service communication patterns", "data consistency approaches" ]) ) print(builder) ``` ### Behavioral and tone constraints Shape the AI's communication style and approach: ```python builder = ( tb.PromptBuilder() .persona("senior developer", "code quality") .task_context("review pull request for junior developer") .constraint("provide constructive, encouraging feedback") .constraint("explain the reasoning behind each suggestion") .constraint("include positive reinforcement for good practices") .constraint("suggest learning resources for improvement areas") .core_analysis([ "code correctness and logic", "security considerations", "maintainability and readability" ]) ) print(builder) ``` ### Context-specific constraints Add domain or situation-specific requirements. In this example for a healthcare application, we focus on HIPAA compliance and patient privacy. ```python builder = ( tb.PromptBuilder() .persona("healthcare software architect", "HIPAA compliance") .critical_constraint("all recommendations must maintain patient privacy") .task_context("design patient data management system") .constraint("consider healthcare industry regulations") .constraint("prioritize data security over performance optimizations") .constraint("include audit trail requirements in recommendations") ) print(builder) ``` ### Multiple related constraints Group related constraints for comprehensive guidance. This example focuses on data analysis with multiple quality constraints: ```python builder = ( tb.PromptBuilder() .persona("data scientist", "business analytics") .task_context("analyze customer behavior patterns") .constraint("support findings with statistical evidence") .constraint("use clear visualizations to illustrate trends") .constraint("explain methodology and assumptions clearly") .constraint("provide actionable business recommendations") .constraint("include confidence levels for predictions") .core_analysis([ "customer segmentation patterns", "behavioral trend analysis", "predictive modeling opportunities" ]) ) print(builder) ``` ### Combining with critical constraints Use standard constraints to complement critical requirements: ```python builder = ( tb.PromptBuilder() .persona("security engineer", "application security") .critical_constraint("Identify blocking security vulnerabilities immediately") .task_context("security audit of web application") .constraint("consider OWASP Top 10 guidelines") # Standard .constraint("evaluate both code and infrastructure security") # Standard .constraint("provide remediation priority levels") # Standard .constraint("include compliance implications where relevant") # Standard .core_analysis([ "authentication and authorization", "input validation and sanitization", "data protection and encryption" ]) ) print(builder) ``` ### Output enhancement constraints We can improve the structure and usability of responses by adding quality-focused constraints: ```python builder = ( tb.PromptBuilder() .persona("technical documentation specialist") .task_context("create troubleshooting guide for deployment issues") .constraint("organize information from most common to least common issues") .constraint("include step-by-step resolution procedures") .constraint("provide prevention strategies for each issue type") .constraint("use consistent formatting and terminology throughout") .output_format([ "issue description and symptoms", "root cause analysis", "step-by-step resolution", "prevention recommendations" ]) ) print(builder) ``` core_analysis(self, analysis_points: Union[str, List[str]]) -> 'PromptBuilder' Define core analysis requirements as a high-priority, required structured section. The core analysis method creates the central analytical framework that defines what specific aspects must be examined and addressed in the AI's response. This method automatically creates a `"CORE ANALYSIS (Required)"` section with high priority placement, ensuring that the fundamental analytical requirements receive prominent attention and are treated as non-negotiable deliverables. Parameters ---------- analysis_points Specific analysis requirements that define the mandatory analytical dimensions. Can be a single string or list of strings. Each point should be clear, actionable, and represent a distinct aspect of the analysis. Points should be formulated as analytical objectives rather than general suggestions (e.g., `"evaluate security implementation patterns"` rather than `"look at security"`). Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Strategic Purpose Framework.** Core analysis requirements serve as the analytical backbone of the prompt, defining the specific dimensions of investigation that must be covered. Unlike general constraints or suggestions, core analysis points are treated as mandatory analytical objectives that structure the AI's systematic examination of the subject matter. **Attention Priority Theory.** This method automatically assigns `Priority.HIGH` and marks the section as required, ensuring that core analysis requirements are prominently positioned after critical constraints and task context but before standard constraints and formatting requirements. This placement leverages attention optimization principles to ensure analytical objectives receive appropriate focus. **Analytical Framework Design.** Each analysis point should represent a distinct analytical dimension or investigative angle that contributes to comprehensive coverage of the task. The points work together to create a systematic analytical framework that guides the AI's examination process and ensures thorough, structured analysis. **Quality Assurance Mechanism.** By marking core analysis as required, this method establishes analytical accountability and the AI must address each specified analysis point to provide a complete response. This prevents superficial analysis and ensures comprehensive coverage of critical analytical dimensions. Integration Notes ----------------- - **Analytical Structure**: creates systematic framework for comprehensive analysis - **High Priority Placement**: automatically positioned prominently in the prompt hierarchy - **Required Coverage**: marked as required to ensure all analytical dimensions are addressed - **Quality Assurance**: establishes analytical accountability and prevents superficial responses - **Systematic Investigation**: guides AI through structured, thorough examination process - **Comprehensive Coverage**: ensures critical analytical aspects are not overlooked The `.core_analysis()` method provides the analytical backbone for sophisticated prompts, ensuring that complex tasks receive systematic, thorough examination across all critical dimensions while maintaining focus on the most important analytical objectives. Examples -------- ### Software architecture analysis Define core analytical requirements for architectural review: ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("senior software architect", "enterprise systems") .critical_constraint("focus on production-ready, scalable solutions") .task_context("review microservices architecture for e-commerce platform") .core_analysis([ "evaluate service decomposition strategy and boundaries", "assess inter-service communication patterns and protocols", "analyze data consistency and transaction management approaches", "review scalability patterns and load distribution mechanisms", "examine security implementation across service boundaries" ]) ) print(builder) ``` ### Security audit analysis Structure mandatory security analysis dimensions: ```python builder = ( tb.PromptBuilder() .persona("security engineer", "application security") .critical_constraint("prioritize critical vulnerabilities that block deployment") .task_context("conduct comprehensive security audit of web application") .core_analysis([ "analyze authentication and authorization mechanisms", "evaluate input validation and sanitization practices", "assess data protection and encryption implementations", "review API security and rate limiting strategies", "examine logging, monitoring, and incident response capabilities" ]) ) print(builder) ``` ### Code quality review analysis Define analytical framework for code review: ```python builder = ( tb.PromptBuilder() .persona("senior developer", "code quality and best practices") .task_context("review pull request for production deployment") .core_analysis([ "evaluate logic correctness and edge case handling", "assess performance implications and optimization opportunities", "review maintainability and code organization patterns", "analyze test coverage and quality assurance approaches", "examine security considerations and vulnerability patterns" ]) .constraint("provide constructive feedback with learning opportunities") .constraint("include positive reinforcement for good practices") ) print(builder) ``` ### Data science model analysis Structure analytical requirements for ML model evaluation: ```python builder = ( tb.PromptBuilder() .persona("data scientist", "machine learning and model evaluation") .critical_constraint("include bias detection and fairness assessment") .task_context("evaluate machine learning model for production deployment") .core_analysis([ "assess model accuracy across different demographic groups", "evaluate feature importance and model interpretability", "analyze training data quality and representation", "review model generalization and overfitting indicators", "examine deployment considerations and monitoring requirements" ]) ) print(builder) ``` ### Business process analysis Define analytical framework for process improvement: ```python builder = ( tb.PromptBuilder() .persona("business analyst", "process optimization") .task_context("analyze customer onboarding process for efficiency improvements") .core_analysis([ "map current process flow and identify bottlenecks", "evaluate customer experience and friction points", "assess resource utilization and cost implications", "analyze compliance and risk management considerations", "identify automation opportunities and technology solutions" ]) .constraint("support recommendations with quantitative analysis") .constraint("consider both short-term wins and long-term strategy") ) print(builder) ``` ### Financial analysis framework Structure comprehensive financial evaluation: ```python builder = ( tb.PromptBuilder() .persona("financial analyst", "portfolio and risk management") .critical_constraint("include regulatory compliance considerations") .task_context("analyze investment portfolio performance and risk exposure") .core_analysis([ "evaluate return performance across asset classes and time periods", "assess risk metrics including VaR, correlation, and concentration", "analyze portfolio diversification and asset allocation effectiveness", "review stress testing results and scenario analysis", "examine liquidity management and cash flow projections" ]) ) print(builder) ``` structured_section(self, title: str, content: Union[str, List[str]], priority: talk_box.prompt_builder.Priority = , required: bool = False) -> 'PromptBuilder' Add a structured section with clear hierarchical boundaries and visual organization. Structured sections create distinct attention clusters that prevent attention drift in complex prompts by providing clear visual and cognitive boundaries around related content. Each section is formatted with an uppercase title and organized content, enabling the AI model to process information in logical, digestible chunks while maintaining focus on specific aspects of the task. Parameters ---------- title Section heading that will be converted to uppercase for clear visual separation. Should be descriptive and specific to the content type (e.g., `"Review Areas"`, `"Performance Metrics"`, `"Security Requirements"`, etc.). The title helps create mental models for information organization. content Section content provided as either a single string or a list of items. When provided as a list, each item is automatically formatted with bullet points for clear visual organization. Content should be specific, actionable, and relevant to the section's purpose. priority Attention priority level for section placement in the final prompt structure. Higher priority sections appear earlier in the prompt to leverage primacy effects. Defaults to `Priority.MEDIUM` for balanced attention allocation. required Whether to mark the section as required in the output by appending `"(Required)"` to the section title. This visual indicator emphasizes critical sections that must be addressed in the response. Defaults to `False`. Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Attention Clustering Theory.** Creates distinct attention clusters for preventing attention drift in complex prompts. The structured approach leverages cognitive psychology principles of chunking and visual hierarchy to improve information processing and comprehension. **Cognitive Boundary Management.** Structured sections group related information together, creating focused attention zones that help the model process complex requirements systematically. This prevents attention from being scattered across disconnected information and maintains cognitive coherence throughout the prompt. **Visual Hierarchy Psychology.** Each section uses uppercase titles and consistent formatting to create clear visual boundaries. This visual organization helps both human readers and AI models navigate complex prompts more effectively by leveraging established patterns of visual information processing. **Priority-Based Information Architecture.** Sections are automatically ordered by priority and insertion order in the final prompt, ensuring that higher-priority content receives appropriate attention placement while maintaining logical information flow that aligns with cognitive processing patterns. Integration Notes ----------------- - **Attention Clustering**: creates focused information zones that prevent cognitive overload - **Visual Organization**: consistent formatting improves prompt readability and navigation - **Priority-Based Ordering**: sections are automatically sorted by priority for optimal attention flow - **Flexible Content**: supports both single-string and list-based content organization - **Requirement Emphasis**: required sections receive visual emphasis to ensure coverage - **Cognitive Chunking**: information is organized in digestible units that align with human processing limits The `.structured_section()` method provides a powerful tool for organizing complex information in attention-optimized ways, enabling the creation of sophisticated prompts that maintain clarity and focus while addressing multiple aspects of complex tasks. Examples -------- ### Basic structured section Create a simple section with clear organization: ```python import talk_box as tb # Single-item structured section builder = ( tb.PromptBuilder() .persona("software architect", "system design") .task_context("review microservices architecture") .structured_section( "Architecture Principles", "focus on scalability, maintainability, and fault tolerance" ) ) print(builder) ``` ### List-based structured section Use list format for multiple related items: ```python # Multi-item structured section builder = ( tb.PromptBuilder() .persona("security engineer", "application security") .task_context("conduct security audit of web application") .structured_section( "Security Focus Areas", [ "authentication and authorization mechanisms", "input validation and sanitization", "data encryption and protection", "API security and rate limiting" ] ) ) print(builder) ``` ### High-priority required section Create critical sections that must be addressed: ```python # High-priority required section builder = ( tb.PromptBuilder() .persona("data scientist", "machine learning") .task_context("evaluate model performance and bias") .structured_section( "Model Validation", [ "accuracy metrics across demographic groups", "bias detection and mitigation strategies", "cross-validation and generalization testing", "ethical considerations and fairness metrics" ], priority=tb.Priority.HIGH, required=True ) ) print(builder) ``` ### Multiple sections with different priorities Build comprehensive prompts with multiple organized sections: ```python # Complex prompt with multiple structured sections builder = ( tb.PromptBuilder() .persona("technical lead", "code review and mentorship") .critical_constraint("focus on production readiness and team learning") .task_context("review pull request for junior developer") .structured_section( "Code Quality Assessment", [ "logic correctness and edge case handling", "security vulnerabilities and best practices", "performance implications and optimizations", "code readability and maintainability" ], priority=tb.Priority.HIGH, required=True ) .structured_section( "Learning Opportunities", [ "design patterns that could be applied", "best practices worth highlighting", "areas for skill development", "recommended learning resources" ], priority=tb.Priority.MEDIUM ) .structured_section( "Team Knowledge Sharing", [ "patterns that could be standardized", "documentation improvements needed", "opportunities for pair programming", "code that exemplifies good practices" ], priority=tb.Priority.LOW ) ) print(builder) ``` ### Domain-specific structured sections Create sections tailored to specific industries or contexts. Here's an example for healthcare: ```python builder = ( tb.PromptBuilder() .persona("healthcare software architect", "HIPAA compliance") .task_context("review patient data management system") .structured_section( "HIPAA Compliance Requirements", [ "patient data encryption and access controls", "audit trail and logging mechanisms", "data minimization and retention policies", "breach detection and notification procedures" ], priority=tb.Priority.CRITICAL, required=True ) ) print(builder) ``` And here's one for finance: ```python builder = ( tb.PromptBuilder() .persona("financial systems architect", "regulatory compliance") .task_context("design trading system architecture") .structured_section( "Regulatory Considerations", [ "market data handling and latency requirements", "trade reporting and compliance monitoring", "risk management and circuit breakers", "audit trails and regulatory reporting" ], priority=tb.Priority.HIGH, required=True ) ) print(builder) ``` ### Performance and optimization sections Structure performance-related requirements clearly: ```python builder = ( tb.PromptBuilder() .persona("performance engineer", "web application optimization") .task_context("optimize application performance for high traffic") .structured_section( "Performance Targets", [ "page load times under 2 seconds", "API response times under 100ms", "support for 10,000 concurrent users", "99.9% uptime availability" ], priority=tb.Priority.HIGH, required=True ) .structured_section( "Optimization Areas", [ "frontend asset optimization and caching", "database query performance and indexing", "CDN implementation and edge caching", "server-side rendering and lazy loading" ], priority=tb.Priority.MEDIUM ) ) print(builder) ``` ### Research and analysis sections Structure analytical requirements and methodologies: ```python # Research analysis prompt builder = ( tb.PromptBuilder() .persona("research analyst", "market intelligence") .task_context("analyze emerging technology adoption trends") .structured_section( "Research Methodology", [ "quantitative data analysis and statistical testing", "qualitative interviews and survey analysis", "competitive landscape and market mapping", "trend analysis and future projections" ], priority=tb.Priority.HIGH, required=True ) .structured_section( "Deliverable Requirements", [ "executive summary with key findings", "detailed methodology and data sources", "visual charts and trend illustrations", "actionable recommendations and next steps" ], priority=tb.Priority.MEDIUM, required=True ) ) print(builder) ``` ### Mixed content types in sections Combine different content formats within sections: ```python builder = ( tb.PromptBuilder() .persona("technical writer", "API documentation") .task_context("create comprehensive API documentation") .structured_section( "documentation Standards", "follow OpenAPI 3.0 specification for consistency and completeness" ) .structured_section( "Required Documentation Elements", [ "endpoint descriptions with purpose and usage", "request/response schemas with examples", "authentication and authorization details", "error codes and troubleshooting guidance" ], required=True ) ) print(builder) ``` avoid_topics(self, topics: Union[str, List[str]]) -> 'PromptBuilder' Specify topics or behaviors to avoid through negative constraints that guide AI responses away from unwanted content. Negative constraints provide explicit guidance about what the AI should not include or discuss in its response, creating clear boundaries that prevent unwanted content, inappropriate suggestions, or off-topic discussions. This method adds an "Avoid:" constraint that appears in the standard constraints section, providing clear guidance about prohibited topics or approaches. Parameters ---------- topics Specific topics, behaviors, approaches, or content areas that should be explicitly avoided in the response. Can be a single string or list of strings. Each item should be clearly defined and specific enough to provide clear guidance (e.g., `"controversial political opinions"`, `"deprecated technologies"`, `"cost-cutting through layoffs"`, `"quick fixes without testing"`, etc.). Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Negative Guidance Psychology.** Research in cognitive psychology shows that explicit negative instructions can be effective when combined with positive guidance. By clearly stating what to avoid, this method helps the AI navigate complex topics while staying within appropriate boundaries and maintaining focus on desired outcomes. **Boundary Setting Mechanism.** Avoid topics serves as a content filter and boundary-setting mechanism that prevents responses from venturing into sensitive, irrelevant, or counterproductive areas. This is particularly valuable for professional contexts where certain topics or approaches could be inappropriate or harmful. **Risk Mitigation Strategy.** Negative constraints help mitigate risks associated with AI-generated content by explicitly excluding potentially problematic topics, biased perspectives, or approaches that could lead to harmful or inappropriate recommendations. **Focus Enhancement Theory.** By eliminating distracting or irrelevant topics, `.avoid_topics()` helps maintain laser focus on the core objectives and prevents the AI from exploring tangential areas that might dilute the quality or relevance of the response. Integration Notes ----------------- - **Boundary Setting**: establishes clear content and approach boundaries for AI responses - **Risk Mitigation**: prevents problematic or inappropriate content through explicit exclusion - **Focus Enhancement**: eliminates distracting topics to maintain response relevance - **Professional Standards**: ensures responses align with ethical and professional guidelines - **Quality Assurance**: prevents low-quality approaches through negative guidance - **Complementary Constraints**: works alongside positive constraints to create comprehensive guidance The `.avoid_topics()` method provides essential boundary-setting capabilities that ensure AI responses remain appropriate, focused, and aligned with professional standards while explicitly excluding problematic approaches or content areas that could compromise response quality or appropriateness. Examples -------- ### Technical architecture review Avoid outdated or problematic technologies and approaches for a bot focused on modern software architecture: ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("solution architect", "modern enterprise systems") .task_context("design scalable microservices architecture for e-commerce platform") .core_analysis([ "service decomposition strategy", "inter-service communication patterns", "data consistency approaches", "scalability and performance optimization" ]) .avoid_topics([ "monolithic architecture patterns", "deprecated Java EE technologies", "synchronous blocking communication", "database shared between services", "manual deployment processes" ]) .output_format([ "architecture overview with service boundaries", "technology stack recommendations", "implementation roadmap with phases" ]) ) print(builder) ``` ### Business strategy consultation Avoid ethically questionable or short-term approaches when advising on business strategy: ```python builder = ( tb.PromptBuilder() .persona("business consultant", "sustainable growth strategies") .task_context("develop growth strategy for struggling retail company") .core_analysis([ "market positioning and competitive advantages", "operational efficiency improvements", "customer experience enhancements", "revenue diversification opportunities" ]) .avoid_topics([ "mass layoffs as primary cost reduction", "exploiting regulatory loopholes", "aggressive customer data monetization", "environmental impact trade-offs for profit", "anti-competitive pricing strategies" ]) .constraint("focus on sustainable, long-term solutions") .output_format([ "strategic assessment with market analysis", "growth initiatives with ethical considerations", "implementation timeline with stakeholder impact" ]) ) print(builder) ``` ### Security audit guidance Avoid security through obscurity and weak practices: ```python builder = ( tb.PromptBuilder() .persona("security engineer", "application security best practices") .task_context("audit web application security for financial services company") .core_analysis([ "authentication and authorization mechanisms", "data protection and encryption standards", "input validation and sanitization", "infrastructure security configuration" ]) .avoid_topics([ "security through obscurity approaches", "custom cryptographic implementations", "storing passwords in plain text or weak hashing", "disabling security features for convenience", "ignoring OWASP recommendations" ]) .critical_constraint("all recommendations must follow industry security standards") .output_format([ "security assessment with risk levels", "critical vulnerabilities requiring immediate attention", "best practice implementation roadmap" ]) ) print(builder) ``` ### Educational content development Avoid outdated or confusing learning approaches by specifying poor pedagogical practices: ```python builder = ( tb.PromptBuilder() .persona("instructional designer", "modern programming education") .task_context("create comprehensive Python programming curriculum for beginners") .core_analysis([ "progressive skill building sequence", "hands-on practice opportunities", "real-world application examples", "common mistake prevention strategies" ]) .avoid_topics([ "memorization-based learning without understanding", "outdated Python 2.x syntax and practices", "complex theoretical concepts before practical foundation", "overwhelming students with too many options", "abstract examples without real-world relevance" ]) .constraint("include diverse learning styles and accessibility considerations") .output_format([ "curriculum structure with learning objectives", "module breakdown with practical exercises", "assessment strategies and progress tracking" ]) ) print(builder) ``` ### Code review guidance Avoid problematic coding practices and shortcuts. For this example, we create a code review prompt that emphasizes constructive feedback while avoiding poor development practices: ```python builder = ( tb.PromptBuilder() .persona("senior developer", "code quality and best practices") .task_context("review pull request for production deployment") .core_analysis([ "code correctness and functionality", "security vulnerability assessment", "performance implications and optimization", "maintainability and documentation quality" ]) .avoid_topics([ "quick fixes that introduce technical debt", "skipping unit tests for faster delivery", "hard-coding configuration values", "ignoring error handling for edge cases", "copy-pasting code without understanding" ]) .constraint("provide constructive feedback with learning opportunities") .output_format([ "code quality assessment with specific examples", "security and performance concerns", "improvement recommendations with rationale" ]) ) print(builder) ``` output_format(self, format_specs: Union[str, List[str]]) -> 'PromptBuilder' Specify output formatting requirements to prevent ambiguous responses and ensure structured deliverables. Output formatting requirements define the structural and organizational expectations for the AI's response, providing clear specifications that prevent ambiguous or inconsistently formatted outputs. These requirements appear in the `"OUTPUT FORMAT"` section near the end of the prompt, ensuring that formatting guidance influences response generation while maintaining the attention hierarchy for more critical content. Parameters ---------- format_specs Specific formatting requirements that define how the response should be structured and organized. Can be a single string or a list of strings. Each specification should be clear, actionable, and measurable when possible. Specifications can address organization, headings, lists, examples, priorities, or any structural aspects of the response (e.g., `"Start with executive summary"`, `"Use bullet points for key findings"`, `"Include code examples for each recommendation"`). Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Attention Drift Mitigation.** Addresses attention drift issues by providing specific, measurable formatting constraints that anchor response structure. Clear formatting requirements help maintain cognitive coherence and ensure that complex responses remain organized and accessible to human readers. **Structural Guidance Framework.** Output format specifications serve as response templates that guide the AI's information organization and presentation. Unlike content-focused constraints, these requirements focus on how information should be structured, ordered, and presented to maximize clarity and usability. **Response Quality Enhancement.** Well-defined formatting requirements significantly improve response quality by preventing stream-of-consciousness outputs and ensuring systematic information organization. This is particularly important for complex analytical tasks where information hierarchy and clear structure are essential for comprehension. **Professional Standards Alignment.** Formatting specifications enable alignment with professional documentation standards, report formats, and organizational communication preferences, ensuring that AI-generated content meets workplace and industry expectations. Integration Notes ----------------- - **Response Structure**: provides clear templates for organized, professional outputs - **Cognitive Clarity**: prevents stream-of-consciousness responses through structured guidance - **Quality Assurance**: ensures consistent formatting that meets professional standards - **Information Hierarchy**: guides appropriate organization of complex information - **Accessibility**: improves readability and navigability of AI-generated content - **Professional Alignment**: enables compliance with organizational communication standards The `.output_format()` method ensures that AI responses are well-structured, professionally formatted, and organized in ways that maximize clarity, usability, and impact for human readers across diverse professional contexts. Examples -------- ### Basic formatting requirements Define clear structure for analytical responses in code reviews with bullet points and summaries within the `.output_format()` method: ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("senior developer", "code review") .task_context("review pull request for production deployment") .core_analysis([ "security vulnerabilities and risks", "performance implications and optimizations", "code quality and maintainability issues" ]) .output_format([ "start with overall assessment (approve/request changes)", "list critical issues that must be fixed", "provide suggestions for improvements", "include positive feedback on good practices" ]) ) print(builder) ``` ### Executive reporting format Structure responses for business stakeholders with clear sections and prioritized findings: ```python builder = ( tb.PromptBuilder() .persona("business analyst", "strategic planning") .task_context("analyze market expansion opportunity") .core_analysis([ "market size and growth potential", "competitive landscape analysis", "risk assessment and mitigation strategies", "resource requirements and timeline" ]) .output_format([ "executive summary (2-3 key sentences)", "detailed findings with supporting data", "risk assessment with mitigation strategies", "recommended action items with priorities", "timeline and resource requirements" ]) ) print(builder) ``` ### Technical documentation format Structure comprehensive technical documentation with clear sections and examples: ```python builder = ( tb.PromptBuilder() .persona("technical writer", "API documentation") .task_context("create comprehensive API reference documentation") .core_analysis([ "endpoint functionality and purpose", "request/response schemas and examples", "authentication and authorization requirements", "error handling and status codes" ]) .output_format([ "overview section with API purpose and scope", "authentication section with setup instructions", "endpoint documentation with examples", "error codes reference with troubleshooting", "SDK and integration examples" ]) ) print(builder) ``` ### Research and analysis format Structure academic or research-style outputs with an output format that includes methodology, findings, and recommendations: ```python builder = ( tb.PromptBuilder() .persona("research analyst", "data science") .task_context("analyze customer behavior patterns from survey data") .core_analysis([ "demographic segmentation and trends", "behavioral pattern identification", "statistical significance of findings", "predictive modeling opportunities" ]) .output_format([ "methodology section with data sources and approach", "key findings with statistical evidence", "visual descriptions for charts and graphs", "limitations and confidence intervals", "recommendations with supporting rationale" ]) ) print(builder) ``` example(self, input_example: str, output_example: str) -> 'PromptBuilder' Add an input/output example for few-shot learning and response format demonstration. Examples are a powerful few-shot learning technique that provides concrete demonstrations of expected input/output patterns, helping the AI understand the desired response format, style, and level of detail. Examples appear in the `"EXAMPLES"` section near the end of the prompt, allowing the model to learn from specific demonstrations while maintaining the attention hierarchy for core content. Parameters ---------- input_example Example input that represents a typical or representative case that the AI might encounter. Should be realistic, relevant to the task context, and demonstrate the type and complexity of input the AI will be processing. The input should be specific enough to provide clear guidance while being generalizable to similar scenarios. output_example Expected output format and content that demonstrates the desired response style, level of detail, structure, and quality. Should exemplify the formatting requirements, analytical depth, and professional standards expected in the actual response. The output should be comprehensive enough to serve as a template while being specific to the input provided. Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Few-Shot Learning Theory.** Examples leverage the AI model's ability to learn from demonstrations without explicit training. By providing concrete input/output pairs, examples enable the model to infer patterns, styles, and expected behaviors that might be difficult to specify through constraints alone. **Response Calibration Mechanism.** Examples serve as calibration tools that help establish the appropriate level of detail, technical depth, formatting style, and analytical approach for responses. This is particularly valuable for complex tasks where abstract descriptions of requirements might be ambiguous. **Pattern Recognition Enhancement.** Multiple examples can demonstrate variations in approach, showing how different types of inputs should be handled while maintaining consistent output quality and format. This helps the AI generalize appropriately across different scenarios. **Quality Anchoring Psychology.** Examples set quality expectations by demonstrating high-quality responses that serve as benchmarks for the AI's own outputs. This helps maintain consistency and professionalism across different prompt executions. Integration Notes ----------------- - **Few-Shot Learning**: leverages AI's pattern recognition for improved response quality - **Format Demonstration**: shows concrete examples of expected output structure and style - **Quality Calibration**: establishes benchmarks for response depth and professionalism - **Variation Handling**: multiple examples can demonstrate different scenarios and approaches - **Learning Reinforcement**: examples reinforce other prompt elements like constraints and formatting - **Prompt Positioning**: examples appear late in prompt to provide final guidance before response generation The `.example()` method provides powerful demonstration-based learning that significantly improves response quality, consistency, and alignment with expectations through concrete input/output pattern recognition rather than abstract instruction following. Examples -------- ### Code review example Demonstrate expected code review format and depth while providing constructive feedback: ````python import talk_box as tb builder = ( tb.PromptBuilder() .persona("senior developer", "code quality and security") .task_context("review Python code for security and best practices") .core_analysis([ "security vulnerabilities and risks", "code quality and maintainability", "performance optimization opportunities", "best practice adherence" ]) .example( input_example=''' def authenticate_user(username, password): query = "SELECT * FROM users WHERE username = '" + username + "' AND password = '" + password + "'" result = db.execute(query) return len(result) > 0 ''', output_example=''' **CRITICAL SECURITY ISSUE**: SQL Injection Vulnerability - **Problem**: direct string concatenation in SQL query allows SQL injection attacks - **Risk Level**: high, and could lead to a data breach or unauthorized access - **Fix**: use parameterized queries or ORM methods - **Example Fix**: ```python query = "SELECT * FROM users WHERE username = %s AND password = %s" result = db.execute(query, (username, password)) ``` **SECURITY ISSUE**: Plain Text Password Storage - **Problem**: passwords should never be stored or compared in plain text - **Fix**: implement password hashing with salt (e.g., bcrypt, scrypt) **CODE QUALITY**: function should return user object, not boolean **PERFORMANCE**: consider adding database indexes on username field''' ) .output_format([ "start with critical security issues", "include specific code examples and fixes", "provide risk assessment for each issue", "end with positive feedback where applicable" ]) ) print(builder) ```` ### Data analysis example Demonstrate analytical depth and presentation style using structured findings and recommendations: ````python builder = ( tb.PromptBuilder() .persona("data scientist", "business analytics") .task_context("analyze customer behavior data and provide insights") .core_analysis([ "customer segmentation patterns", "behavioral trends and anomalies", "statistical significance of findings", "business recommendations" ]) .example( input_example="customer purchase data showing 15% increase in mobile transactions but 8% decrease in desktop purchases over Q3", output_example=''' **KEY FINDING**: Mobile-First Customer Behavior Shift **Statistical Analysis**: - Mobile transactions: +15% (p < 0.01, statistically significant) - Desktop transactions: -8% (p < 0.05, statistically significant) - Net transaction volume: +3.2% overall growth **Customer Segmentation**: - Millennials (25-40): 67% mobile preference, driving the increase - Gen X (41-55): 45% mobile adoption, slower transition - Baby Boomers (55+): 23% mobile usage, prefer desktop **Business Implications**: 1. **Mobile Optimization Priority**: Invest in mobile UX improvements 2. **Desktop Support**: Maintain desktop experience for older demographics 3. **Cross-Platform Strategy**: Develop unified experience across devices **Recommendations**: - Allocate 70% of UX budget to mobile optimization - Implement responsive design improvements - Create mobile-specific promotional campaigns''' ) ) print(builder) ```` ### Business analysis example Demonstrate strategic analysis format in business contexts with clear sections and actionable recommendations: ````python builder = ( tb.PromptBuilder() .persona("business consultant", "strategic planning") .task_context("analyze market expansion opportunity") .core_analysis([ "market size and growth potential", "competitive landscape assessment", "resource requirements and ROI", "risk factors and mitigation" ]) .example( input_example="SaaS company considering expansion into European markets, currently serving 50k US customers", output_example=''' **EXECUTIVE SUMMARY**: European expansion presents significant opportunity with estimated 3-year ROI of 180% **MARKET ANALYSIS**: - Total Addressable Market: €2.3B (growing 12% annually) - Immediate Serviceable Market: €180M across UK, Germany, France - Competitive Gap: Limited players in mid-market segment **FINANCIAL PROJECTION**: - Year 1: €2M investment, €800K revenue - Year 2: €1.2M additional investment, €3.2M revenue - Year 3: €5.8M revenue, 18% profit margin - Break-even: Month 14 **KEY SUCCESS FACTORS**: 1. GDPR compliance and data localization 2. Local partnerships for market entry 3. Multi-language product localization 4. European customer support team **RISK MITIGATION**: - Regulatory: Early GDPR consultation (€50K budget) - Competition: Differentiated pricing strategy - Execution: Phased rollout starting with UK market **RECOMMENDATION**: Proceed with expansion, starting Q2 2024 ''' ) ) print(builder) ```` ### Educational content example Show educational content format with clear learning objectives and hands-on exercises: ````python builder = ( tb.PromptBuilder() .persona("programming instructor", "Python education") .task_context("Create lesson on Python data structures") .core_analysis([ "Concept explanation with clear examples", "Progressive skill building exercises", "Common mistakes and debugging", "Real-world applications" ]) .example( input_example="Teach Python dictionaries to intermediate beginners", output_example=''' **LEARNING OBJECTIVE**: Master Python dictionaries for data organization and lookup **CONCEPT EXPLANATION**: Dictionaries store key-value pairs, like a real-world dictionary where you look up words (keys) to find definitions (values). ```python # Creating a dictionary student = { "name": "Alice", "age": 20, "major": "Computer Science" } ``` **HANDS-ON EXERCISE**: ```python # Task: Create an inventory system inventory = {"apples": 50, "bananas": 30, "oranges": 25} # Add new item inventory["grapes"] = 40 # Update quantity inventory["apples"] += 10 # Check if item exists if "mangoes" in inventory: print(f"Mangoes: {inventory['mangoes']}") else: print("Mangoes not in stock") ``` **COMMON MISTAKES**: 1. Using mutable objects as keys (lists, other dictionaries) 2. Forgetting that dictionaries are unordered (Python < 3.7) 3. KeyError when accessing non-existent keys **REAL-WORLD APPLICATION**: User authentication, configuration settings, caching data ''' ) ) print(builder) ```` ### Multiple examples for variation Use multiple examples to show different scenarios and approaches within the same prompt: ````python builder = ( tb.PromptBuilder() .persona("senior developer", "code mentorship") .task_context("provide educational code review for junior developers") .core_analysis([ "code correctness and logic", "best practices and patterns", "performance considerations", "learning opportunities" ]) .example( input_example="simple function with basic logic error", output_example="focus on explaining the logic error clearly with corrected version and learning points" ) .example( input_example="complex function with performance issues", output_example="analyze algorithmic complexity, suggest optimizations, explain trade-offs between readability and performance" ) .example( input_example="well-written code with minor style issues", output_example="acknowledge good practices, suggest minor improvements, reinforce positive patterns" ) ) print(builder) ```` final_emphasis(self, emphasis: str) -> 'PromptBuilder' Set final emphasis that leverages recency bias to ensure critical instructions receive maximum attention. Final emphasis strategically positions the most important instruction at the very end of the system prompt, leveraging the psychological principle of recency bias to ensure that critical guidance remains fresh in the AI's attention during response generation. This method provides a powerful way to reinforce the most essential requirement or constraint that must not be overlooked. Parameters ---------- emphasis The most critical instruction or objective that must receive primary attention during response generation. Should be formulated as a clear, actionable directive that captures the essential requirement (e.g., `"focus your entire response on practical implementation steps"`, `"prioritize security considerations above all else"`, `"ensure all recommendations are cost-effective and implementable"`, etc.). Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Recency Bias Psychology.** Research in cognitive psychology demonstrates that information presented at the end of a sequence receives heightened attention and retention. By placing critical instructions at the prompt's conclusion, final emphasis ensures that the most important guidance influences the AI's response generation process when attention is most focused on producing output. **Attention Anchoring Mechanism.** Final emphasis serves as an attention anchor that prevents drift from core objectives during complex prompt processing. When prompts contain extensive context, constraints, and examples, the final emphasis acts as a cognitive reset that refocuses attention on the primary objective before response generation begins. **Override Mechanism Theory.** Final emphasis can serve as an override mechanism for complex prompts where multiple competing priorities might create confusion. By explicitly stating the most critical requirement at the end, this method ensures that primary objectives take precedence over secondary considerations when trade-offs must be made. **Quality Assurance Strategy.** The strategic placement of final emphasis helps prevent AI responses that technically satisfy prompt requirements but miss the primary intent. This is particularly valuable for complex analytical tasks where technical completeness might overshadow the core objective. Integration Notes ----------------- - **Recency Bias Leverage**: strategically positions critical guidance at prompt conclusion for maximum impact - **Attention Anchoring**: prevents objective drift during complex prompt processing - **Priority Override**: ensures primary objectives take precedence when trade-offs are required - **Quality Assurance**: prevents technically complete but intent-missing responses - **Cognitive Reset**: refocuses attention on core objectives before response generation - **Strategic Positioning**: complements front-loaded critical constraints with end-positioned emphasis The `.final_emphasis()` method provides a powerful attention management tool that ensures the most critical requirements maintain prominence throughout the AI's response generation process, leveraging psychological principles to maximize adherence to primary objectives. Examples -------- ### Security-focused analysis Ensure security remains the primary consideration despite other requirements using the `.final_emphasis()` method: ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("security engineer", "application security") .task_context("review web application for deployment readiness") .core_analysis([ "authentication and authorization mechanisms", "input validation and data sanitization", "infrastructure security configuration", "compliance with security standards" ]) .constraint("include performance optimization suggestions") .constraint("consider user experience implications") .output_format([ "executive summary with risk assessment", "critical security issues requiring immediate attention", "performance and UX recommendations where applicable" ]) .final_emphasis( "security vulnerabilities must be identified and addressed before " "any performance or UX considerations" ) ) print(builder) ``` ### Cost-conscious recommendations Emphasize budget constraints in business analysis by placing cost considerations at the end: ```python builder = ( tb.PromptBuilder() .persona("business consultant", "strategic planning") .task_context("develop growth strategy for startup with limited funding") .core_analysis([ "market opportunity assessment", "competitive landscape analysis", "resource requirements and scaling plan", "revenue generation strategies" ]) .constraint("include innovative growth tactics") .constraint("consider partnership opportunities") .output_format([ "executive summary with growth potential", "detailed strategy with implementation phases", "resource allocation and timeline" ]) .final_emphasis( "all recommendations must be implementable with minimal upfront investment " "and show clear ROI within 6 months" ) ) print(builder) ``` ### Learning-focused code review Prioritize educational value in technical feedback through the use of final emphasis: ```python builder = ( tb.PromptBuilder() .persona("senior developer", "mentorship and code quality") .task_context("review junior developer's code for learning and improvement") .core_analysis([ "code correctness and functionality", "best practices and design patterns", "performance optimization opportunities", "security considerations" ]) .constraint("identify areas for improvement") .constraint("provide specific examples and fixes") .output_format([ "overall assessment with learning objectives", "technical issues with explanations and solutions", "positive reinforcement for good practices" ]) .final_emphasis( "frame all feedback as learning opportunities with clear explanations of why " "changes improve the code" ) ) print(builder) ``` ### User experience priority Ensure UX considerations override technical preferences. This is particularly important in product management and design contexts: ```python builder = ( tb.PromptBuilder() .persona("product manager", "user experience and design") .task_context("evaluate new feature proposal for mobile application") .core_analysis([ "user needs and problem-solution fit", "technical implementation complexity", "performance and scalability impact", "business value and metrics" ]) .constraint("consider technical feasibility constraints") .constraint("include development effort estimates") .output_format([ "feature assessment with user impact analysis", "implementation recommendations", "success metrics and validation plan" ]) .final_emphasis( "user experience and accessibility must be prioritized over technical " "convenience or development speed" ) ) print(builder) ``` ### Quality over quantity emphasis Prioritize depth and thoroughness over breadth. With the `.final_emphasis()` method, ensure that the AI focuses on high-impact content rather than trying to address every possible issue. ```python builder = ( tb.PromptBuilder() .persona("content strategist", "editorial quality") .task_context("evaluate content library for quality and effectiveness") .core_analysis([ "content accuracy and factual verification", "engagement metrics and user feedback", "SEO optimization and discoverability", "brand consistency and messaging alignment" ]) .constraint("include competitive analysis") .constraint("consider content volume requirements") .output_format([ "content quality assessment", "priority improvement areas", "content strategy recommendations" ]) .final_emphasis( "focus on identifying and improving the highest-impact content pieces rather " "than addressing all content issues superficially" ) ) print(builder) ``` vocabulary(self, terms: Union[talk_box.prompt_builder.VocabularyTerm, List[talk_box.prompt_builder.VocabularyTerm]]) -> 'PromptBuilder' Add domain-specific vocabulary definitions to ensure consistent understanding of terminology. The vocabulary method provides the AI with a professional glossary of terms specific to your domain, similar to what professionals use to maintain consistent understanding of specialized terminology. This helps ensure the AI correctly interprets domain-specific language and responds using appropriate terminology. Parameters ---------- terms Domain-specific terms with their definitions and optional synonyms. Can be a single `VocabularyTerm` or a list of `VocabularyTerm` items for batch addition. Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods. Research Foundation ------------------- **Domain Knowledge Anchoring**: Explicit vocabulary definitions help establish consistent domain context and prevent misinterpretation of specialized terminology that may have different meanings in general contexts. **Semantic Consistency**: Providing clear definitions ensures the AI maintains consistent understanding of terms throughout the conversation, even when users employ synonyms or alternative phrasings. Examples -------- ### Basic single term usage This examples shows how to add a single vocabulary term to establish a domain context. ```python import talk_box as tb churn_term = tb.VocabularyTerm( term="Customer Churn", definition=( "Percentage of customers who stop using our service during a specific time period." ), synonyms=["attrition rate", "customer turnover", "subscription cancellation rate"] ) builder = ( tb.PromptBuilder() .persona("customer success manager") .vocabulary(churn_term) .task_context("Analyze customer retention patterns and improvement strategies") ) print(builder) ``` ### Multilingual vocabulary for global operations Here's an example where we create an internationalized vocabulary with language-aware synonyms in the domain of global hotel management. ```python import talk_box as tb room_types = [ tb.VocabularyTerm( term="Ocean View Room", definition="Premium rooms on floors 15-20 with direct Atlantic Ocean visibility.", synonyms=[ "seaside room", "beach view", "waterfront suite", "es:habitación con vista al mar", "fr:chambre vue sur mer", "de:Meerblickzimmer", "pt-BR:quarto vista oceano" ] ), tb.VocabularyTerm( term="Concierge Level", definition=( "Exclusive access tier with dedicated concierge services and premium amenities" ), synonyms=[ "VIP services", "premium tier", "exclusive access", "es:nivel concierge", "fr:niveau concierge", "de:Concierge-Service" ] ) ] builder = ( tb.PromptBuilder() .persona("multilingual hotel booking assistant") .vocabulary(room_types) .task_context("Assist international guests with room selections and amenities") ) print(builder) ``` ### Healthcare domain vocabulary with translations Define medical terminology with official translations (through the `translations=` attribute of `VocabularyTerm`) for international healthcare systems. ```python healthcare_vocab = [ tb.VocabularyTerm( term="Electronic Health Record", definition=( "Digital version of patient medical history maintained by healthcare " "providers including diagnoses, medications, treatment plans, and test results." ), synonyms=["EHR", "electronic medical record", "EMR", "digital health record"], translations={ "es": "Registro Médico Electrónico", "fr": "Dossier Médical Électronique", "de": "Elektronische Patientenakte", "pt": "Registro Eletrônico de Saúde" } ), tb.VocabularyTerm( term="Clinical Decision Support", definition=( "Health information technology that provides healthcare professionals with " "patient-specific assessments and evidence-based treatment recommendations" ), synonyms=["CDS", "decision support system", "clinical guidance system"], translations={ "es": "Soporte de Decisiones Clínicas", "fr": "Aide à la Décision Clinique", "de": "Klinische Entscheidungsunterstützung", "pt": "Apoio à Decisão Clínica" } ), tb.VocabularyTerm( term="Health Level Seven", definition=( "International standard for exchanging healthcare information between " "different healthcare systems and applications." ), synonyms=[ "HL7", "healthcare interoperability standard", "medical data exchange protocol" ], translations={ "es": "Nivel Siete de Salud", "fr": "Niveau Sept Santé", "de": "Gesundheitsstufe Sieben", "pt": "Nível Sete de Saúde" } ) ] builder = ( tb.PromptBuilder() .persona("healthcare IT consultant", "medical informatics and system integration") .vocabulary(healthcare_vocab) .constraint("Maintain strict patient privacy and HIPAA compliance") .avoid_topics([ "medical diagnosis", "treatment recommendations", "patient-specific medical advice" ]) .task_context("Design interoperable healthcare information systems") ) print(builder) ``` See Also -------- - `VocabularyTerm`: Complete documentation for creating domain-specific terminology with multilingual support, translations, and comprehensive examples pathways(self, pathway_spec) -> 'PromptBuilder' Add conversational pathway guidance to structure and guide conversation flow. Pathways provide flexible conversation flow guidance that helps AI assistants navigate complex interactions while maintaining natural conversation patterns. This method requires a `Pathways` object created using the chainable Pathways API, which defines states, transitions, and flow control logic for structured conversations. The method enables sophisticated conversation flow management while preserving the natural, adaptive qualities that make AI conversations engaging and user-friendly. Parameters ---------- pathway_spec A `Pathways` object created using the chainable Pathways API, or a dictionary specification containing pathway definition. The specification includes states, transitions, information requirements, and flow control logic. Returns ------- PromptBuilder Self for method chaining, allowing combination with other prompt building methods to create comprehensive, structured prompts. Research Foundation ------------------- **Conversational State Management Theory.** Unlike rigid state machines, pathways serve as intelligent guardrails that adapt to user behavior while ensuring important steps and information gathering requirements are addressed. This approach balances structure with conversational flexibility, allowing natural dialogue patterns while maintaining systematic progress toward objectives. **Adaptive Flow Psychology.** Pathways provide conversation guidance without enforcing rigid adherence, allowing the AI to adapt to natural conversation patterns while ensuring key objectives are met. This balances structure with conversational flexibility and helps ensure systematic information gathering and step completion while maintaining user-friendly interactions. **Attention Optimization Integration.** Pathway specifications are integrated into the prompt structure at an optimal position for AI attention, providing clear guidance without overwhelming other prompt components. This strategic positioning ensures that conversation flow guidance receives appropriate attention while maintaining the overall prompt's cognitive load balance. Integration Notes ----------------- - **Flexible Guidance**: pathways provide structure without rigidity, allowing natural conversation flow - **Information Gathering**: systematic collection of required information while maintaining user experience - **Adaptive Branching**: support for conditional flows based on user responses and circumstances - **Tool Integration**: clear guidance on when and how to use external tools within the conversation flow - **Completion Tracking**: built-in success conditions and completion criteria for complex processes The `.pathways()` method enables sophisticated conversation flow management while preserving the natural, adaptive qualities that make AI conversations engaging and user-friendly. Examples -------- ### Customer support pathway Create a structured support flow: ```python import talk_box as tb # Define support pathway support_pathway = ( tb.Pathways( title="Technical Support", desc="systematic technical problem resolution", activation=["user reports technical issues", "user needs troubleshooting help"] ) # === STATE: problem_identification === .state("understand the technical problem") .required(["issue description", "error messages", "recent changes"]) .next_state("basic_diagnostics") # === STATE: basic_diagnostics === .state("basic diagnostics: determine if basic fixes might work") .branch_on("simple configuration issue", id="quick_fix") .branch_on("complex system problem", id="advanced_diagnostics") # === STATE: quick_fix === .state("quick fix: provide immediate solution steps") .success_condition("problem is resolved") # === STATE: advanced_diagnostics === .state("advanced diagnostics: perform detailed system analysis") .success_condition("root cause identified and resolved") ) # Use in prompt prompt = ( tb.PromptBuilder() .persona("technical support specialist", "troubleshooting") .pathways(support_pathway) .final_emphasis("Follow pathway while adapting to user needs") ) ``` print(self) -> None Print the assembled prompt to stdout. Equivalent to `print(str(builder))`. Useful for quick inspection during interactive development. Examples -------- ```{python} import talk_box as tb builder = tb.PromptBuilder().persona("analyst", "data science") builder.print() ``` Priority(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Control where a prompt section is placed relative to other sections. `PromptBuilder` uses priority levels to order sections so that the most important content lands in the regions of the prompt where LLM attention is strongest (typically the beginning and end). Assign a priority when calling builder methods such as `structured_section()` or when constructing a `PromptSection` directly. Values ------ - `CRITICAL`: placed at the very front of the prompt for maximum attention - `HIGH`: placed early, right after critical sections - `MEDIUM`: placed in the middle of the prompt (the default for most builder methods) - `LOW`: placed toward the end for supporting or secondary information Examples -------- ```{python} import talk_box as tb builder = ( tb.PromptBuilder() .persona("analyst", "data analysis") .structured_section( "Key Constraints", ["Use only public data", "Cite sources"], priority=tb.Priority.CRITICAL, ) ) print(str(builder)[:100]) ``` %seealso PromptSection, PromptBuilder PromptSection(content: str, priority: talk_box.prompt_builder.Priority = , section_type: str = 'general', order_hint: int = 0) -> None Represents a structured section of an attention-optimized prompt with priority and ordering metadata. The `PromptSection` class is a fundamental building block used by `PromptBuilder` to create sophisticated, attention-optimized prompts. Each section encapsulates content along with metadata that controls how the section is positioned and prioritized within the final prompt. This enables precise control over attention flow and information hierarchy. **Integration with PromptBuilder**: While users can create `PromptSection` objects directly, they are typically created automatically by `PromptBuilder` methods. The sections are then assembled according to attention principles to create optimized final prompts. This design provides both high-level convenience through `PromptBuilder` and fine-grained control through direct `PromptSection` manipulation. **Attention Optimization**: Each section contributes to the overall attention strategy: - **Priority**: determines relative importance and influences final ordering - **Section Type**: enables grouping and specialized handling of content types - **Order Hint**: provides fine-grained control over section positioning - **Content**: the actual prompt text optimized for the section's role The combination of these attributes allows the prompt building system to create prompts that leverage attention mechanisms effectively, ensuring critical information receives appropriate model focus while maintaining natural conversation flow. Parameters ---------- content The text content of the prompt section. This is the actual text that will appear in the final prompt. Content should be crafted to serve the section's specific purpose within the overall prompt strategy. priority Attention priority level determining section placement order and emphasis. Higher priority sections are typically placed in more prominent positions. Defaults to `Priority.MEDIUM`. section_type Type classification for the section enabling specialized handling and grouping. This allows the prompt builder to apply type-specific optimization strategies. Defaults to `"general"`. order_hint Fine-grained ordering hint where lower numbers appear earlier in the prompt. This provides precise control over section positioning beyond priority levels. Sections with the same priority are ordered by this value. Defaults to `0`. Returns ------- PromptSection A new prompt section with the specified content and metadata. Priority Levels --------------- The available priority levels are: - `Priority.CRITICAL`: highest importance, placed prominently - `Priority.HIGH`: important content requiring strong attention - `Priority.MEDIUM`: standard priority for general content - `Priority.LOW`: supporting information, de-emphasized placement - `Priority.MINIMAL`: background context, least prominent placement Section Types ------------- Common section types include: - `"persona"`: role and behavioral context - `"constraint"`: requirements and limitations - `"analysis"`: core analysis tasks and objectives - `"format"`: output formatting requirements - `"example"`: input/output examples and demonstrations - `"emphasis"`: final reinforcement and focus directives - `"general"`: general-purpose content Section Lifecycle ----------------- Prompt sections typically follow this lifecycle within the prompt building process: 1. **Creation**: sections are created with content and metadata 2. **Collection**: multiple sections are gathered by the PromptBuilder 3. **Sorting**: sections are ordered by priority and order_hint values 4. **Grouping**: sections are grouped by type for specialized handling 5. **Assembly**: final prompt is constructed from ordered sections 6. **Optimization**: content is refined for attention and coherence Design Principles ----------------- **Attention Optimization**: sections are designed to work together to guide model attention effectively, with priority and positioning controlling information hierarchy. **Modularity**: each section encapsulates a specific aspect of the prompt, enabling reusable components and systematic prompt construction. **Flexibility**: the section system supports both structured workflows through standard section types and custom applications through extensible metadata. **Composability**: sections can be combined, reordered, and manipulated to create sophisticated prompt strategies for different use cases. **Cognitive Alignment**: section design aligns with cognitive psychology principles like primacy/recency effects and information chunking for optimal comprehension. Integration Notes ----------------- - **Automatic Ordering**: when used with `PromptBuilder`, sections are automatically ordered by priority and order_hint for optimal attention flow - **Type-Based Processing**: section types enable specialized handling and validation within the prompt building pipeline - **Content Optimization**: section content should be crafted for clarity and specificity to maximize prompt effectiveness - **Memory Efficiency**: sections are lightweight dataclasses suitable for large-scale prompt construction workflows The `PromptSection` class provides the foundation for systematic, attention-optimized prompt engineering, enabling both simple prompt construction and sophisticated multi-component prompt strategies. Examples -------- ### Creating basic prompt sections Create sections for different types of prompt content: ```python import talk_box as tb # High-priority persona section persona_section = tb.PromptSection( content="You are a senior software architect with expertise in distributed systems.", priority=tb.Priority.CRITICAL, section_type="persona", order_hint=1 ) # Critical constraint section constraint_section = tb.PromptSection( content="Focus only on scalability issues that impact performance.", priority=tb.Priority.CRITICAL, section_type="constraint", order_hint=2 ) # Medium-priority analysis section analysis_section = tb.PromptSection( content="Analyze the system architecture for bottlenecks and optimization opportunities.", priority=tb.Priority.MEDIUM, section_type="analysis", order_hint=10 ) print(f"Persona: {persona_section.content}") print(f"Priority: {persona_section.priority}") print(f"Type: {persona_section.section_type}") ``` ### Working with section priorities Use priorities to control attention hierarchy: ```python # Create sections with different priorities sections = [ tb.PromptSection( content="Secondary consideration: Check for code style consistency.", priority=tb.Priority.LOW, section_type="analysis" ), tb.PromptSection( content="CRITICAL: Identify security vulnerabilities immediately.", priority=tb.Priority.CRITICAL, section_type="constraint" ), tb.PromptSection( content="Important: Focus on performance bottlenecks.", priority=tb.Priority.HIGH, section_type="analysis" ), tb.PromptSection( content="Background context: This is a financial application.", priority=tb.Priority.MINIMAL, section_type="general" ) ] ``` ### Using section types for specialized handling Organize content by type for targeted optimization: ```python # Create sections representing different prompt components prompt_sections = [ tb.PromptSection( content="You are an expert code reviewer.", priority=tb.Priority.CRITICAL, section_type="persona" ), tb.PromptSection( content="Focus on security issues and performance problems.", priority=tb.Priority.HIGH, section_type="constraint" ), tb.PromptSection( content="Analyze the code for bugs, security flaws, and inefficiencies.", priority=tb.Priority.MEDIUM, section_type="analysis" ), tb.PromptSection( content="Format: List critical issues first, then suggestions.", priority=tb.Priority.MEDIUM, section_type="format" ), tb.PromptSection( content="Example: 'CRITICAL: SQL injection vulnerability on line 42'", priority=tb.Priority.LOW, section_type="example" ) ] ``` ### Fine-grained ordering with order_hint Use order_hint for precise section positioning: ```python # Create sections with same priority but different order hints setup_sections = [ tb.PromptSection( content="You are a helpful assistant.", priority=tb.Priority.HIGH, section_type="persona", order_hint=1 # First ), tb.PromptSection( content="You specialize in Python programming.", priority=tb.Priority.HIGH, section_type="persona", order_hint=2 # Second ), tb.PromptSection( content="You focus on writing clean, efficient code.", priority=Priority.HIGH, section_type="persona", order_hint=3 # Third ) ] ``` ### Building sections for different prompt strategies Create sections optimized for specific attention patterns: ```python # Front-loading critical information (primacy bias) critical_first = tb.PromptSection( content="IMMEDIATE PRIORITY: Check for buffer overflow vulnerabilities.", priority=tb.Priority.CRITICAL, section_type="constraint", order_hint=1 ) # Core task definition main_task = tb.PromptSection( content="Review this C++ code for security issues and memory management problems.", priority=tb.Priority.HIGH, section_type="analysis", order_hint=10 ) # Final emphasis (recency bias) final_emphasis = tb.PromptSection( content="Remember: Security vulnerabilities are the highest priority.", priority=Priority.HIGH, section_type="emphasis", order_hint=100 ) ``` ### Integration with PromptBuilder workflow See how sections work within the larger prompt building process: ```python # Create a prompt builder builder = tb.PromptBuilder() # Builder methods create PromptSection objects internally builder.persona("senior developer", "code review") builder.critical_constraint("Focus on security vulnerabilities") builder.core_analysis(["Memory management", "Input validation", "Error handling"]) # You can also add custom sections directly custom_section = tb.PromptSection( content="Pay special attention to authentication mechanisms.", priority=tb.Priority.HIGH, section_type="constraint", order_hint=5 ) # Add custom section to builder's internal collection builder.sections.append(custom_section) # Build final prompt (sections are automatically ordered and assembled) final_prompt = builder print("Final assembled prompt:") print(final_prompt) ``` ### Advanced section manipulation Perform sophisticated operations on section collections: ```python # Create a collection of mixed sections mixed_sections = [ tb.PromptSection("Core task", tb.Priority.HIGH, "analysis", 1), tb.PromptSection("Important constraint", tb.Priority.HIGH, "constraint", 2), tb.PromptSection("Background info", tb.Priority.LOW, "general", 3), tb.PromptSection("Critical requirement", tb.Priority.CRITICAL, "constraint", 0), tb.PromptSection("Output format", tb.Priority.MEDIUM, "format", 4) ] # Filter high-priority sections high_priority = [s for s in mixed_sections if s.priority.value >= tb.Priority.HIGH.value] # Find all constraint sections constraints = [s for s in mixed_sections if s.section_type == "constraint"] # Get earliest section by order_hint earliest = min(mixed_sections, key=lambda s: s.order_hint) # Calculate total content length total_length = sum(len(s.content) for s in mixed_sections) print(f"High priority sections: {len(high_priority)}") print(f"Constraint sections: {len(constraints)}") print(f"Earliest section: {earliest.content}") print(f"Total content length: {total_length} characters") ``` ### Custom section types for specialized workflows Define custom section types for specific applications: ```python # Custom section types for code review workflow code_review_sections = [ tb.PromptSection( content="You are a senior code reviewer with 10+ years experience.", priority=tb.Priority.CRITICAL, section_type="reviewer_persona" ), tb.PromptSection( content="This code will be deployed to production systems.", priority=tb.Priority.HIGH, section_type="deployment_context" ), tb.PromptSection( content="Check: Security, Performance, Maintainability, Testing", priority=tb.Priority.HIGH, section_type="review_checklist" ), tb.PromptSection( content="Format: Critical issues first, then improvements, then praise", priority=tb.Priority.MEDIUM, section_type="response_structure" ), tb.PromptSection( content="Remember: Constructive feedback builds better developers.", priority=tb.Priority.MEDIUM, section_type="review_philosophy" ) ] # Process sections by custom type workflow_map = { "reviewer_persona": "Sets reviewer identity and expertise", "deployment_context": "Provides operational context", "review_checklist": "Defines evaluation criteria", "response_structure": "Controls output organization", "review_philosophy": "Guides feedback tone and approach" } print("Code review workflow sections:") for section in code_review_sections: purpose = workflow_map.get(section.section_type, "General purpose") print(f"• {section.section_type}: {purpose}") print(f" Content: {section.content}") print() ``` VocabularyTerm(term: str, definition: str, synonyms: Optional[List[str]] = None, translations: Optional[Dict[str, str]] = None) -> None Define domain-specific terminology with multilingual support for consistent AI understanding. `VocabularyTerm` creates a professional glossary entry that ensures AI systems correctly interpret specialized terminology within specific business or technical contexts. These terms are designed to integrate seamlessly with `PromptBuilder` through the `.vocabulary()` method, where individual `VocabularyTerm` objects or lists of terms can be added to enhance prompt clarity and domain-specific understanding. Unlike general language understanding, domain vocabulary provides precise definitions that prevent misinterpretation of terms that may have different meanings across industries, regions, or organizational contexts. The class supports sophisticated multilingual environments through language-aware synonyms and translations, enabling AI assistants to understand and respond appropriately when users employ terminology in different languages or regional variants. Parameters ---------- term The primary term or phrase being defined. Should be the canonical name used within your organization or domain. Can include multi-word phrases, technical terminology, product names, or specialized concepts that require explicit definition within your context. definition Precise definition of what this term means in your specific domain context. Should be clear, unambiguous, and focused on the operational meaning rather than general dictionary definitions. Include relevant scope, constraints, or contextual boundaries that distinguish this term's usage in your domain. synonyms Alternative ways users might refer to this term, including colloquial expressions, abbreviations, industry variants, and multilingual alternatives. Supports language-aware formatting using `"lang:synonym"` or `"locale:synonym"` notation (e.g., `"es:cuota de mercado"`, `"de-AT:Marktanteil"`, `"fr-CA:part de marché"`) for international contexts. translations A dictionary of direct translations of the primary term for different languages and locales. Keys should use standard language codes (ISO 639-1/639-2) (e.g., `"es"`, `"de"`, `"fr"`, etc.) or locale codes (e.g., `"es-MX"`, `"de-AT"`, `"fr-CA"`). Values are the translated terms in the target language, maintaining semantic consistency across linguistic contexts. Research Foundation ------------------- **Domain Knowledge Anchoring Theory.** Research in cognitive linguistics demonstrates that specialized domains develop unique terminologies that carry specific semantic loads different from general usage. By explicitly defining domain vocabulary, AI systems can maintain semantic consistency and avoid misinterpretation that occurs when general language models encounter specialized terminology. **Multilingual Semantic Consistency.** Studies in cross-linguistic communication show that direct term-by-term translation often fails to capture domain-specific meanings that have evolved within particular linguistic communities. VocabularyTerm addresses this by enabling explicit definition of how terms should be interpreted across different languages while maintaining semantic fidelity to the original domain concept. **Professional Glossary Psychology.** Research in professional communication demonstrates that shared terminology is foundational to effective domain expertise. By providing explicit vocabulary definitions, AI systems can participate more effectively in professional contexts where precise terminology usage is critical for accuracy, credibility, and operational effectiveness. **Contextual Disambiguation Framework.** Linguistic research shows that many terms carry multiple meanings across different contexts, and successful communication requires explicit disambiguation. VocabularyTerm provides this disambiguation by establishing clear contextual boundaries for term usage within specific domains. Integration Notes ----------------- - **Semantic Consistency**: ensures AI maintains consistent understanding of specialized terminology throughout conversations - **Multilingual Support**: enables accurate interpretation across different languages and regional variants - **Professional Standards**: aligns AI communication with industry-specific terminology conventions - **Context Boundaries**: prevents misinterpretation by establishing clear domain-specific definitions - **User Experience**: improves communication effectiveness by recognizing diverse ways users express domain concepts - **Organizational Knowledge**: captures and standardizes institutional terminology for consistent AI interactions The `VocabularyTerm` class provides essential infrastructure for building domain-aware AI systems that can communicate effectively within specialized contexts while maintaining semantic accuracy across multilingual and multicultural environments. ### Using `translations=` vs `synonyms=` with language codes Understanding the difference between `translations=` and language-coded `synonyms=` is important for effective multilingual vocabulary design. **SYNONYMS with language codes.** Alternative expressions users might use. ```python import talk_box as tb recognition_term = tb.VocabularyTerm( term="Market Penetration Rate", definition="Percentage of target market currently using our services.", synonyms=[ "market share", # English alternative "adoption rate", # Another English way "es:cuota de mercado", # How Spanish users might say it "de:Marktanteil", # How German users might refer to it "fr:part de marché" # How French users might express it ] ) builder = ( tb.PromptBuilder() .persona("international business consultant") .vocabulary(recognition_term) ) print(recognition_term) ``` **TRANSLATIONS.** Official term names in different languages. ```python standardization_term = tb.VocabularyTerm( term="Market Penetration Rate", definition="Percentage of target market currently using our services.", synonyms=["market share", "adoption rate"], # English alternatives only translations={ "es": "Tasa de Penetración de Mercado", # Official Spanish name "de": "Marktdurchdringungsrate", # Official German name "fr": "Taux de Pénétration du Marché" # Official French name } ) builder = ( tb.PromptBuilder() .persona("international business consultant") .vocabulary(standardization_term) ) print(standardization_term) ``` **COMBINED.** Both official translations *and* alternative expressions. ```python comprehensive_term = tb.VocabularyTerm( term="Customer Lifetime Value", definition="Total revenue expected from a customer relationship over time.", synonyms=[ "CLV", # Common abbreviation "lifetime revenue", # English alternative "es:valor del cliente", # Informal Spanish expression "de:Kundenwert", # Casual German way "fr:valeur client" # Shortened French expression ], translations={ "es": "Valor de Vida del Cliente", # Official Spanish translation "de": "Kundenlebenszeitwert", # Official German translation "fr": "Valeur Vie Client" # Official French translation } ) builder = ( tb.PromptBuilder() .persona("international business consultant") .vocabulary(comprehensive_term) ) print(builder) ``` The output clearly shows the difference: - **Translations** appear as `"[Translations: de:Marktdurchdringungsrate, es:Tasa de...]"` - **Synonyms** appear as `"(Also: market share, de:Marktanteil, es:cuota de mercado)"` Use `synonyms=` with language codes** when users might naturally refer to concepts using different languages, informal terms, or abbreviations. Use `translations=` when you need to establish official, standardized terminology across languages. Examples -------- ### Defining single vocabulary terms Let's define a single term for a customer success context. A useful pattern is to generate a `VocabularyTerm` object and then introduce it into a `PromptBuilder` via its `.vocabulary()` method. ```python import talk_box as tb # Single term for customer success domain churn_term = tb.VocabularyTerm( term="Customer Churn", definition=( "The percentage of customers who stop using our service during a specific time period." ), synonyms=["attrition rate", "customer turnover", "subscription cancellation rate"] ) # Use in prompt builder builder = tb.PromptBuilder().vocabulary(churn_term) print(builder) ``` ### Defining multiple vocabulary terms You might have to define several `VocabularyTerm` objects to cover different aspects of your domain. For that, create a list of `VocabularyTerm` objects and then pass that list object to the `.vocabulary()` method of `PromptBuilder`. This example shows how to define technical terminology for software development contexts using a list of `VocabularyTerm` objects. ```python tech_vocab = [ tb.VocabularyTerm( term="Blue-Green Deployment", definition=( "Deployment strategy using two identical production environments where traffic " "is switched between them to enable zero-downtime releases." ), synonyms=[ "blue green strategy", "dual environment deployment", "zero downtime deployment", ] ), tb.VocabularyTerm( term="Circuit Breaker Pattern", definition=( "Microservices resilience pattern that prevents cascading failures by monitoring " "service health and temporarily blocking requests to failing services" ), synonyms=[ "circuit breaker", "failure isolation pattern", "resilience pattern", ] ), tb.VocabularyTerm( term="Service Mesh", definition=( "Infrastructure layer that handles service-to-service communication, security, " "and observability in microservices architectures." ), synonyms=[ "mesh architecture", "service communication layer", "microservices mesh", ] ) ] builder = ( tb.PromptBuilder() .persona("DevOps architect", "cloud infrastructure and microservices") .vocabulary(tech_vocab) .task_context("Design resilient microservices architecture") ) print(builder) ``` ### Multilingual vocabulary items We can mark pieces of vocabulary with language codes to indicate the language or locale for which a synonym applies. This enables precise multilingual support where users may refer to terminology in different languages or regional variants. In this example, we create international vocabulary with language-aware synonyms for global operations of hotel management. ```python room_types = [ tb.VocabularyTerm( term="Ocean View Room", definition="Premium rooms on floors 15-20 with direct Atlantic Ocean visibility.", synonyms=[ "seaside room", "beach view", "waterfront suite", "es:habitación con vista al mar", "fr:chambre vue sur mer", "de:Meerblickzimmer", "pt-BR:quarto vista oceano" ] ), tb.VocabularyTerm( term="Concierge Level", definition=( "Exclusive access tier with dedicated concierge services and premium amenities." ), synonyms=[ "VIP services", "premium tier", "exclusive access", "es:nivel concierge", "fr:niveau concierge", "de:Concierge-Service" ] ) ] builder = ( tb.PromptBuilder() .persona("multilingual hotel booking assistant") .vocabulary(room_types) ) print(builder) ``` ### Healthcare domain vocabulary Here's an example of defining medical and healthcare terminology with precision requirements. ```python healthcare_vocab = [ tb.VocabularyTerm( term="Electronic Health Record", definition=( "Digital version of patient medical history maintained by healthcare providers, " "including diagnoses, medications, treatment plans, and test results." ), synonyms=[ "EHR", "electronic medical record", "EMR", "digital health record", "es:historia clínica electrónica", "fr:dossier médical électronique", "de:elektronische Patientenakte" ] ), tb.VocabularyTerm( term="Clinical Decision Support", definition=( "Health information technology that provides healthcare professionals with " "patient-specific assessments and evidence-based treatment recommendations." ), synonyms=[ "CDS", "decision support system", "clinical guidance system", "es:apoyo a decisiones clínicas", "fr:aide à la décision clinique", "de:klinische Entscheidungsunterstützung" ] ), tb.VocabularyTerm( term="Health Level Seven", definition=( "International standard for exchanging healthcare information between different " "healthcare systems and applications." ), synonyms=[ "HL7", "healthcare interoperability standard", "medical data exchange protocol", "es:estándar de interoperabilidad sanitaria", "fr:norme interopérabilité santé", "de:Gesundheitsdatenstandard" ] ) ] builder = ( tb.PromptBuilder() .persona("healthcare IT consultant", "medical informatics and system integration") .vocabulary(healthcare_vocab) .constraint("Maintain strict patient privacy and HIPAA compliance") .avoid_topics([ "medical diagnosis", "treatment recommendations", "patient-specific medical advice" ]) ) print(builder) ``` architectural_analysis_prompt() -> talk_box.prompt_builder.PromptBuilder Create a pre-configured `PromptBuilder` for architectural analysis. The returned builder includes a senior-architect persona, a task-context section, core analysis dimensions (frameworks, data models, API design), a legacy-assessment structured section, and an output-format specification. Customize it further by chaining additional builder methods. Returns ------- PromptBuilder A builder pre-loaded with architectural analysis sections. Examples -------- ```{python} import talk_box as tb builder = tb.architectural_analysis_prompt() print(str(builder)[:200]) ``` %seealso code_review_prompt, debugging_prompt, PromptBuilder code_review_prompt() -> talk_box.prompt_builder.PromptBuilder Create a pre-configured `PromptBuilder` for code review. The builder includes a senior-engineer persona, core analysis dimensions covering security, performance, maintainability, best practices, and testing, plus an output format that groups findings by severity. Extend it with additional constraints or sections as needed. Returns ------- PromptBuilder A builder pre-loaded with code-review sections. Examples -------- ```{python} import talk_box as tb builder = tb.code_review_prompt() print(str(builder)[:200]) ``` %seealso architectural_analysis_prompt, debugging_prompt, PromptBuilder debugging_prompt() -> talk_box.prompt_builder.PromptBuilder Create a pre-configured `PromptBuilder` for debugging. The builder sets up an expert-debugger persona, a critical constraint to target root causes, a required "Analysis Steps" section (reproduce, trace, identify, fix), and an output format that structures the response into problem summary, reproduction steps, root-cause analysis, and recommended fix. Returns ------- PromptBuilder A builder pre-loaded with debugging sections. Examples -------- ```{python} import talk_box as tb builder = tb.debugging_prompt() print(str(builder)[:200]) ``` %seealso architectural_analysis_prompt, code_review_prompt, PromptBuilder ## Conversation Pathways State-machine conversation flows with branching and fallbacks Pathways(title: str, desc: str = '', activation: Union[str, List[str], NoneType] = None, completion_criteria: Union[str, List[str], NoneType] = None, fallback_strategy: str = None) Chainable builder for defining structured conversational pathways. The `Pathways` class provides intelligent conversation flow guidance while maintaining flexibility to adapt to natural conversation patterns. They serve as guardrails rather than rigid state machines, helping LLMs provide consistent and thorough assistance while remaining responsive to user needs and conversational context. Parameters ---------- title A short, descriptive name for the pathway. desc Clear, concise explanation of the pathway's purpose and scope. activation Specific situations or user intents that trigger pathway activation. Can be a single string or a list of strings. completion_criteria High-level conditions that indicate the pathway's objectives have been fully achieved. Can be a single string or a list of strings. Optional. fallback_strategy General approach for handling situations where the pathway doesn't apply or users need different support. Optional. Returns ------- Pathways The configured `Pathways` object for further chaining with `.state()` and other methods. Building Pathways ----------------- Building a pathway follows a specific sequence that ensures proper configuration and flow logic. Each step builds upon the previous one to create a coherent conversation structure. ### 1. Pathway Setup (call once, in order) ```python pathway = ( tb.Pathways( title="Title", desc="Purpose and scope", # What this pathway does activation=[...], # When to use this pathway completion_criteria=[...], # What makes pathway successful fallback_strategy="..." # Handle unexpected situations ) # First .state() call automatically becomes the starting state ``` ### 2. State Definition ```python pathway = ( tb.Pathways( title="Support Flow", desc="Customer support pathway", activation="User needs help" ) # === STATE: intake === .state("intake: gather customer information") .required(["issue description", "contact info"]) .next_state("triage") # === STATE: triage === .state("triage: route to appropriate support") .branch_on("Technical issue", id="tech_support") .branch_on("Billing question", id="billing") # === STATE: tech_support === .state("tech support: resolve technical problems") .success_condition("Issue resolved") ) ``` This approach provides: - visual state boundaries with `# === STATE: description ===` comments - natural state definition with shorthand syntax: `.state("id: what happens here")` - smart type inference where `.tools()` → `"tool"`, `.branch_on()` → `"decision"`, `.required()` → `"collect"` - automatic start state where the first `.state()` becomes the starting state ### 3. State Configuration Pattern (repeat for each state): ```python # Define the state with description first .state("What happens in this state", id="state_name") .state("info: collect required information") # inferred as "collect", id="info" .state("make decision: evaluate options and choose") # "make decision" → id="make_decision" .state("use tools: apply specific capabilities") # type inferred as "tool" from .tools() .state("final summary: provide conclusion", type="summary") # explicit type with shorthand syntax .state("Wrap up") # Linear states don't really need IDs # Configure the state .required([...]) # What must be accomplished .optional([...]) # What would be nice to have .tools([...]) # Available tools (infers type="tool") .success_condition("When state succeeds") # How to know it's complete # Define state transitions (choose one) .next_state("next_state") # Linear progression .branch_on("condition", id="target_state") # Conditional (infers type="decision") .next_state("common_state") # Reconverge after branching .fallback("error_condition", "backup_state") # Error handling ``` State Types and Their Purpose ----------------------------- Each state type serves a specific role in the conversation flow: - `type="chat"`: open conversation, explanations, guidance (default) - `type="decision"`: branching logic, must use `branch_on()` not `next_state()` - `type="collect"`: structured information gathering - `type="tool"`: using specific tools or APIs, requires `tools()` - `type="summary"`: conclusions, confirmations, completion actions Key Rules --------- - description is required and provided in `.state()` method - if you use `type="decision"`, you must use `branch_on()` and never `next_state()` - `type="tool"` must include a `tools()` specification - state names must be unique and use `"lowercase_with_underscores"` - target states in transitions must be defined later with another `.state()` Examples -------- The following examples demonstrate common pathway patterns that address different conversation needs. The first shows a simple linear flow where states progress sequentially, ideal for straightforward processes. The second illustrates branching logic that routes users down different paths before converging to a common endpoint, which is good for triage and support scenarios. ### Simple Linear Flow This password reset pathway demonstrates the basic pattern: setup the pathway, define states sequentially, and specify what information each state needs to collect. Notice how each state builds naturally toward the goal of helping the user regain access to their account. ```python import talk_box as tb simple_pathway = ( tb.Pathways( title="Password Reset", desc="Help users reset their forgotten passwords", activation=["User can't log in", "User forgot password"], completion_criteria="User successfully logs in with new password", fallback_strategy="If user lacks access to recovery methods, escalate to manual verification" ) # === STATE: verification === .state("verification: verify user identity") .required(["email address", "account verification"]) .next_state("password_update") # === STATE: password_update === .state("password update: guide user through creating new password") .required(["new password is created", "password requirements are met"]) .success_condition("User successfully logs in with new password") ) ``` This linear flow moves step-by-step from identity verification to password creation. Each state has clear requirements and success conditions, making the pathway easy to follow and validate. ### Branching Flow with Decision Points This customer support pathway demonstrates decision state branching using the unified `.state()` method. Notice how different support paths merge back to a common completion state, ensuring consistent wrap-up regardless of the support type provided. ```python support_pathway = ( tb.Pathways( title="Customer Support", desc="route and resolve customer inquiries", activation=["user needs help", "user reports problem"], completion_criteria=["customer issue fully resolved", "customer satisfied"], fallback_strategy="if issue is complex, escalate to human support" ) # === STATE: triage === .state("triage: determine the type of support needed") .branch_on("Technical problem reported", id="technical_support") .branch_on("Billing question asked", id="billing_support") .branch_on("General inquiry made", id="general_help") # === STATE: technical_support === .state("technical support: diagnose and resolve technical issues") .tools(["system_diagnostics", "troubleshooting_guide"]) .success_condition("Technical issue is resolved") .next_state("completion") # === STATE: billing_support === .state("billing support: address billing and account questions") .required(["billing issue is understood", "solution is provided"]) .next_state("completion") # === STATE: completion === .state("completion: ensure customer satisfaction and wrap up", type="summary") .required(["issue resolved confirmation", "follow up if needed"]) .success_condition("Customer satisfaction confirmed") ) ``` This branching example shows how `.state()` creates clear decision points that route conversations appropriately, then merge back together for consistent completion. Inspecting Pathways ------------------- Once you've built a pathway, you can inspect it using different string representations: ```python import talk_box as tb # Create a simple pathway pathway = ( tb.Pathways( title="Quick Help", desc="Provide rapid assistance", activation="User needs help", completion_criteria="User's problem is resolved", fallback_strategy="If problem is complex, escalate to specialized support" ) # === STATE: problem_intake === .state("problem intake: understand the issue details") .required(["issue description"]) .next_state("provide_solution") # === STATE: provide_solution === .state("provide solution: offer targeted assistance") .success_condition("User's problem is resolved") ) ``` We can view the pathway in two ways, either as a brief summary by examining the object itself: ```python pathway ``` Or with `print()` for a more detailed view: ```python print(pathway) ``` The summary view gives you a quick overview, while the detailed view shows the state types, description, and other configuration details. This is especially useful when debugging complex pathways or understanding existing pathway configurations. state(self, desc: str, id: str = None, type: str = None, agent: str = None) -> 'Pathways' Define a state with natural language description as the primary identifier. The first state you define becomes the starting state automatically. State type is inferred from subsequent method calls, making the API more intuitive and reducing the need to specify types upfront. Parameters ---------- desc Clear description of the state's purpose and what should happen. This is the primary identifier and should be specific about the expected interaction or outcome. Supports shorthand syntax: use `"id: description"` format to specify both ID and description in one parameter (e.g., `"completion: ensure customer satisfaction and wrap up"`). The ID part will be automatically normalized (spaces converted to underscores, etc.). id Optional unique identifier for the state. Required only when other states need to reference this state (via `.branch_on()`, `.next_state()`). If not provided, an ID will be extracted from `desc` using `"id: description"` format if present, otherwise auto-generated. If explicitly provided, shorthand parsing is bypassed. type Optional explicit state type. If not provided, the type will be inferred from subsequent method calls Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Research Foundation ------------------- **State Type Inference System.** Based on method usage, the state type is automatically inferred to reduce cognitive load and API complexity. The inference follows this hierarchy: `.tools()` → `"tool"`, `.branch_on()` → `"decision"`, `.required()` → `"collect"`, with `"chat"` as the default. If multiple methods suggest different types, the first inference takes precedence to maintain consistency. **Automatic Start State Management.** The first state defined automatically becomes the starting state, eliminating the need for explicit start state configuration. This simplifies pathway creation while ensuring every pathway has a clear entry point for conversation flow. **ID Generation and Reference System.** When no explicit ID is provided, the system auto-generates snake_case identifiers from state descriptions, ensuring uniqueness through numeric suffixes when conflicts occur. IDs are only required when other states need to reference the state for transitions or branching. Integration Notes ----------------- - **Description Priority**: description always comes first as the primary identifier - **Reference Requirements**: ID only needed when other states need to reference this state - **Shorthand Syntax**: use `"id: description"` format to combine ID and description in one parameter for cleaner syntax; ID part is automatically normalized (spaces → underscores) - **Explicit ID Priority**: when `id=` parameter is provided, shorthand parsing is bypassed - **Type Inference**: inferred from usage patterns to reduce explicit configuration - **Conflict Resolution**: first method call determines type, conflicts generate warnings - **Auto-generation**: IDs use `snake_case` from description with uniqueness guarantees - **Visual Organization**: use `# === STATE: name ===` comments for visual state separation in complex pathways - **Explicit Type Usage**: consider explicit types for complex workflows, documentation clarity, team development, mixed functionality, or error prevention The `.state()` method creates clear conversation boundaries and progression, with each state having a specific purpose that builds toward the final goal. When to use explicit types: in complex workflows where type inference might be ambiguous, for documentation clarity when the state's purpose isn't obvious from methods, for team development to make intentions explicit, for mixed functionality when a state serves multiple purposes, or as error prevention for avoiding unintended type inference conflicts. Examples -------- Complete pathway showing `.state()` method with both traditional and shorthand syntax: ```python import talk_box as tb # Creating a complete product recommendation pathway pathway = ( tb.Pathways( title="Product Recommendation", desc="Help customers find the right product for their needs", activation="Customer needs product guidance" ) # Traditional syntax: separate id parameter --- # === STATE: welcome === .state("welcome: welcome customer and understand their situation") .required(["the customer's goal", "a budget range"]) .next_state("needs_analysis") # Shorthand syntax: "id: description" format --- # === STATE: needs_analysis === .state("needs analysis: analyze customer requirements and preferences") .required(["specific requirements", "priorities"]) .success_condition("customer needs are clearly understood") .next_state("final_recommendation") # Spaces in ID automatically become underscores --- # === STATE: final_recommendation === .state("final recommendation: present tailored product matches") .required(["product matches", "rationale"]) .success_condition("customer has clear next steps") ) # See how the pathway materializes print(pathway) ``` required(self, info_types: Union[str, List[str]]) -> 'Pathways' Specify required information for the current state to be considered complete. Use to define what must be obtained before the state can transition to the next step. The LLM will focus on gathering this information before proceeding. Can be used in any order within the state configuration. Parameters ---------- info_types Essential information that must be collected or established. Can be a single string or a list of strings. Be specific and measurable. Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Integration Notes ----------------- - **State Progression**: state cannot progress until required items are addressed - **Type Inference**: infers state type as `"collect"` if not explicitly set - **Specificity**: be specific and concrete for clear guidance - **Complementary Use**: pair with `.optional()` for nice-to-have information - **Completion Criteria**: use `.success_condition()` to define when requirements are truly met - **Systematic Collection**: ensures thorough data gathering before progression The `.required()` method ensures the LLM won't proceed until essential information is collected, preventing incomplete processes and ensuring thorough data gathering. Examples -------- Complete pathway showing `.required()` defining essential information: ```python import talk_box as tb # Creating a loan application pathway pathway = ( tb.Pathways( title="Loan Application Process", desc="guide customers through loan application requirements", activation="customer wants to apply for a loan" ) # === STATE: personal_info === .state("personal info: gather basic applicant information") # .required() ensures critical data is collected --- .required(["applicant's full name", "current employment status"]) .next_state("financial_details") # === STATE: financial_details === .state("financial details: collect financial information") # .required() can specify multiple essential items --- .required([ "verified annual income amount", "detailed monthly expenses breakdown", "complete existing debt information", "authorization to check credit score" ]) .success_condition("All financial data verified") .next_state("review") # === STATE: review === .state("review: review application completeness") # .required() works with single items too --- .required("applicant's legal signature and consent") .success_condition("application ready for processing") ) # See the pathway with required information highlighted print(pathway) ``` optional(self, info_types: Union[str, List[str]]) -> 'Pathways' Specify optional information that would be helpful but not required. Use to define nice-to-have information that can improve the outcome but isn't essential for state completion. The LLM will attempt to gather this if the conversation allows. Often used alongside `.required()` to create comprehensive information gathering states. Parameters ---------- info_types Additional information that would be beneficial but not essential. Can be a single string or a list of strings. Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Integration Notes ----------------- - **Flexible Progression**: state can progress without optional items - **Enhanced Outcomes**: helps create more comprehensive outcomes when available - **Balanced Flow**: use sparingly as too many optionals can slow the flow - **State Compatibility**: best used in states with `type="collect"` or structured chat states - **Complementary Use**: often used alongside `.required()` to create comprehensive information gathering - **Conversation Adaptation**: allows gathering helpful information when conversation naturally allows The `.optional()` method allows conversations to gather helpful information when available, but doesn't block progress if users want to move forward quickly. Examples -------- Complete pathway showing `.optional()` enhancing outcomes without blocking progress: ```python import talk_box as tb # Creating a travel booking pathway pathway = ( tb.Pathways( title="Flight Booking Assistant", desc="help customers find and book flights", activation="customer wants to book a flight" ) # === STATE: travel_basics === .state("travel basics: gather essential travel details") .required(["departure city", "destination city", "preferred travel date"]) # .optional() adds helpful details without slowing the process ----- .optional([ "return date if roundtrip", "preferred departure time window", "airline preference or loyalty program" ]) .next_state("search_flights") # === STATE: search_flights === .state("search flights: find matching flights") .required("available flight options found and presented") # .optional() can improve personalization --- .optional("preferred seating section or specific seat requests") .success_condition("customer has reviewed flight options") .next_state("booking") # === STATE: booking === .state("booking: complete the booking") .required(["valid payment information", "complete traveler details for all passengers"]) # .optional() for enhanced services --- .optional([ "travel insurance coverage options", "special meal requests or dietary needs", "frequent flyer number for miles credit" ]) .success_condition("booking confirmed") ) # See how optional items enhance the pathway print(pathway) ``` tools(self, tool_names: Union[str, List[str]]) -> 'Pathways' Specify tools available for use in the current state. Essential for `type="tool"` states, but can also be used in other states where specific capabilities are needed. Typically combined with `.success_condition()` to define when tool usage is complete. Parameters ---------- tool_names Names of specific tools or capabilities the LLM should use. Can be a single string or a list of strings. These should match actual available tools. Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Integration Notes ----------------- - **Type Inference**: infers state type as `"tool"` if not explicitly set - **Tool Matching**: tool names should match actual available capabilities - **Completion Criteria**: use `.success_condition()` to define completion criteria - **Error Handling**: consider `.fallback()` for when tools fail - **State Focus**: essential for `type="tool"` states but can be used in other states where specific capabilities are needed - **Capability Specification**: tells the LLM what specific capabilities are available at each step The `.tools()` method tells the LLM what specific capabilities are available at each step, automatically inferring the state type as "tool" when tools are the primary focus. Examples -------- Complete pathway showing `.tools()` enabling specific capabilities: ```python import talk_box as tb # Creating a technical diagnosis pathway pathway = ( tb.Pathways( title="System Diagnostics", desc="diagnose and resolve technical issues", activation="user reports technical problems" ) # === STATE: problem_intake === .state("problem intake: understand the reported issue") .required(["problem description", "system details", "error messages"]) .next_state("initial_diagnosis") # === STATE: initial_diagnosis === .state("initial diagnosis: run initial diagnostic checks") # .tools() specifies what capabilities are available --- .tools([ "system_health_checker", "log_analyzer", "performance_monitor" ]) .success_condition("initial diagnosis completed") .next_state("detailed_analysis") # === STATE: detailed_analysis === .state("detailed analysis: perform detailed system analysis") # .tools() can specify advanced diagnostic tools --- .tools([ "network_diagnostics", "database_integrity_check", "security_scan" ]) .required(["the root cause is identified"]) .next_state("solution") # === STATE: solution === .state("solution: implement solution") # .tools() for implementation capabilities --- .tools("automated_repair_tool") .success_condition("issue resolved and system stable") ) # See how tools are integrated into the pathway print(pathway) ``` success_condition(self, condition: str) -> 'Pathways' Define what indicates successful completion of the current state. Use to specify when the state's objectives are met and it's ready to transition. More specific than just completing `.required()` items. Can be used in any order within the state configuration. Parameters ---------- condition Specific, observable condition indicating the state succeeded. Use action-oriented language that the LLM can recognize. Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Integration Notes ----------------- - **Completion Clarity**: more specific than just completing `.required()` items - **Observable Criteria**: should be observable/confirmable in conversation - **Active Voice**: use active voice like `"user confirms..."` not `"user understanding confirmed"` - **Multiple Conditions**: can have multiple success conditions for complex states - **Progression Control**: prevents premature progression and ensures thorough coverage - **Objective Definition**: specifies when the state's objectives are met and ready to transition The `.success_condition()` method ensures the LLM knows exactly when each step is truly complete, preventing premature progression and ensuring thorough coverage. Examples -------- Complete pathway showing `.success_condition()` defining clear completion criteria: ```python import talk_box as tb # Creating a learning assessment pathway pathway = ( tb.Pathways( title="Skill Assessment", desc="evaluate student understanding and provide targeted feedback", activation="student completes a learning module" ) # === STATE: practice === .state("practice: present practice problems") .required(["problems are attempted", "student provided responses"]) # .success_condition() defines when understanding is demonstrated --- .success_condition("student correctly solves at least 3 out of 5 problems") .next_state("feedback") # === STATE: feedback === .state("feedback: provide personalized feedback") .required(["specific feedback", "improvement areas"]) # .success_condition() ensures feedback is constructive --- .success_condition("student understands their mistakes and next steps") .next_state("advanced_practice") # === STATE: advanced_practice === .state("advanced practice: offer advanced challenges") .required("challenging problems are presented") .optional("hints if needed") # .success_condition() confirms mastery --- .success_condition("student demonstrates confident problem-solving ability") ) # See how success conditions guide the learning process print(pathway) ``` next_state(self, state_name: str) -> 'Pathways' Define direct transition to the next state. Use for linear progression after state completion. Do not use with `type="decision"` states (use `.branch_on()` instead). This creates unconditional forward movement in the pathway. Parameters ---------- state_name Name of the state to transition to next. The target state must be defined later in the pathway using `.state()`. Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Integration Notes ----------------- - **Linear Progression**: creates unconditional transition after state completion - **Decision State Restriction**: cannot be used with `type="decision"` states; use `.branch_on()` instead - **Forward Declaration**: target state must be defined later with `.state()` - **Sequential Flow**: useful for processes with a clear order - **Unconditional Movement**: for conditional logic, use `.branch_on()` - **Straightforward Routing**: creates sequential flows where each step naturally follows the previous The `.next_state()` method creates straightforward, sequential flows where each step naturally follows the previous one, which is good for processes with a clear order. Examples -------- Complete pathway showing `.next_state()` creating linear progression: ```python import talk_box as tb # Creating a customer onboarding pathway pathway = ( tb.Pathways( title="Customer Onboarding", desc="welcome new customers and set up their accounts", activation="new customer signs up" ) # === STATE: welcome === .state("welcome: welcome and collect basic information") .required(["full name", "email", "company name"]) # .next_state() creates smooth linear progression --- .next_state("account_setup") # === STATE: account_setup === .state("account setup: set up account preferences") .required(["password is created", "preferences are selected"]) .success_condition("account is fully configured") # .next_state() continues the sequential flow --- .next_state("feature_tour") # === STATE: feature_tour === .state("feature tour: provide guided feature tour") .required("key features are demonstrated") .success_condition("customer understands main functionality") # .next_state() leads to final step --- .next_state("completion") # === STATE: completion === .state("completion: complete onboarding process") .required(["welcome resources are provided", "next steps are explained"]) .success_condition("customer is ready to use the platform") ) # See the clear linear progression print(pathway) ``` branch_on(self, condition: str, id: str) -> 'Pathways' Define conditional branch to another state based on specific conditions. Use with decision states to create multiple possible transitions based on user responses, detected conditions, or conversation context. Each branch should represent a distinct path through the workflow. Parameters ---------- condition Specific, recognizable condition that triggers this branch. Be concrete and observable in conversation. id Target state ID for this branch condition. The target state must be defined later with `.state()`. Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Integration Notes ----------------- - **Type Inference**: infers current state type as `"decision"` if not explicitly set - **Mutual Exclusivity**: conditions should be mutually exclusive when possible - **Forward Declaration**: each branch must lead to a state defined later with `.state()` - **Concrete Conditions**: be specific like `"user mentions password issues"` not `"user has problems"` - **Smart Routing**: enables routing based on conditions with automatic decision state inference - **Reconvergence**: allows multiple pathways that can reconverge later The `.branch_on()` method enables smart routing based on conditions, automatically inferring the `"decision"` state type and allowing multiple pathways that can reconverge later. Examples -------- Complete pathway showing `.branch_on()` creating conditional routing: ```python import talk_box as tb # Creating a healthcare triage pathway pathway = ( tb.Pathways( title="Medical Triage", desc="route patients to appropriate care based on symptoms", activation="patient seeks medical assistance" ) # === STATE: initial_assessment === .state("initial assessment: assess patient symptoms and urgency") .required(["symptoms are described", "pain level", "duration"]) .success_condition("Symptoms are clearly documented") .next_state("triage_decision") # === STATE: triage_decision === .state("triage decision: determine appropriate care level") .required("urgency is evaluated") # .branch_on() routes based on severity ----- .branch_on("severe or life-threatening symptoms", id="emergency_care") .branch_on("moderate symptoms requiring prompt attention", id="urgent_care") .branch_on("mild symptoms manageable with routine care", id="standard_care") # The first branch leads to emergency care ----- # === STATE: emergency_care === .state("emergency care: initiate emergency protocol") .required(["911 is called", "immediate first aid is provided"]) .success_condition("emergency services are contacted") .next_state("follow_up") # The second branch leads to urgent care ----- # === STATE: urgent_care === .state("urgent care: schedule urgent care appointment") .required(["same day appointment", "preparation instructions"]) .success_condition("urgent care is arranged") .next_state("follow_up") # The third branch leads to standard care ----- # === STATE: standard_care === .state("standard care: provide self-care guidance") .required(["home care instructions", "symptom monitoring"]) .success_condition("patient understands self-care plan") .next_state("follow_up") # === STATE: follow_up === .state("follow up: arrange follow-up care") .required(["follow up is scheduled"]) .success_condition("continuity of care is ensured") ) # See how branching creates appropriate care pathways print(pathway) ``` fallback(self, condition: str, state_name: str) -> 'Pathways' Define fallback transition when normal state progression fails. Use when you need to handle error conditions, user confusion, or when expected outcomes don't occur. Provides graceful recovery paths instead of getting stuck in a state. Parameters ---------- condition Specific condition that triggers the fallback. Usually describes a failure or unexpected situation. state_name State to transition to when fallback condition occurs. Returns ------- Pathways Self for method chaining, allowing combination with other pathway building methods to create comprehensive conversation flows. Integration Notes ----------------- - **Error Handling**: use for error handling and recovery from unexpected situations - **Graceful Degradation**: provides graceful degradation instead of getting stuck - **Failure Scenarios**: condition should describe failure scenarios clearly - **Combined Usage**: can be used alongside `.next_state()` or `.branch_on()` - **Stuck Prevention**: ensures conversations don't get stuck when expected outcomes don't occur - **Recovery Paths**: provides alternative paths for complex scenarios and edge cases The `.fallback()` method ensures conversations don't get stuck when expected outcomes don't occur, providing alternative paths for complex scenarios and edge cases. Examples -------- Complete pathway showing `.fallback()` providing graceful error recovery: ```python import talk_box as tb # Creating a complex problem-solving pathway with fallbacks pathway = ( tb.Pathways( title="Technical Problem Resolution", desc="systematic approach to solving technical issues", activation="user encounters a technical problem" ) # === STATE: problem_analysis === .state("problem analysis: understand the problem details") .required(["problem description", "system context", "error details"]) .success_condition("problem is clearly defined") .next_state("solution_attempt") # === STATE: solution_attempt === .state("solution attempt: apply standard solution") .required(["solution is implemented", "results are verified"]) .success_condition("problem is resolved") # .fallback() handles situations where standard solutions don't work --- .fallback("solution doesn't resolve the issue", "advanced_troubleshooting") .next_state("completion") # === STATE: advanced_troubleshooting === .state("advanced troubleshooting: advanced diagnostic procedures") .tools(["system_diagnostics", "log_analyzer", "network_tracer"]) .required("root cause is identified") .success_condition("advanced solution is implemented") # .fallback() provides escalation when even advanced methods fail ----- .fallback("issue remains unresolved after advanced diagnostics", "expert_escalation") .next_state("completion") # === STATE: expert_escalation === .state("expert escalation: escalate to specialist support") .required(["detailed case summary", "expert is contacted"]) .success_condition("case is transferred to appropriate specialist") .next_state("completion") # === STATE: completion === .state("completion: confirm resolution and document") .required(["resolution is confirmed", "case is documented"]) .success_condition("issue fully resolved and documented") ) # See how fallbacks provide multiple recovery paths print(pathway) ``` agent(self, agent_name: str) -> 'Pathways' Assign an agent to the current state. When a state has an agent, that agent handles all interactions while the pathway is in that state. This enables multi-agent workflows where different states are served by different specialized agents. Parameters ---------- agent_name Name of the agent to handle this state. Register the agent via `register_agent()` before running the pathway. Returns ------- Pathways Self for method chaining. Examples -------- ```python import talk_box as tb pathway = ( tb.Pathways(title="Support", desc="Multi-agent support") .state("triage: classify the issue") .agent("triage_bot") .branch_on("technical", id="tech") .state("tech: resolve technical issues") .agent("tech_expert") ) ``` register_agent(self, name: str, agent: Any) -> 'Pathways' Register an ``Agent`` instance for use in pathway states. Agents registered here can be retrieved later with ``get_agent()`` to handle interactions when the pathway reaches their state. Parameters ---------- name The agent name (must match the name used in ``.state(agent=...)`` or ``.agent(...)``). agent An ``Agent`` instance. Returns ------- Pathways Self for method chaining. Examples -------- ```python import talk_box as tb triage = tb.Agent.from_persona("customer_support_tier1") tech = tb.Agent.from_persona("debugging_assistant") pathway = ( tb.Pathways(title="Support", desc="Multi-agent support") .register_agent("triage", triage) .register_agent("tech", tech) .state("triage: classify issue", agent="triage") .state("tech: resolve issue", agent="tech") ) ``` get_agent(self, state_name: str) -> Any Get the agent assigned to a specific state. Parameters ---------- state_name The state ID to look up. Returns ------- Agent or None The registered ``Agent`` for that state, or ``None`` if no agent is assigned or registered. visualize(self, title: str = None, filename: str = None, auto_open: bool = True) -> str Create an HTML visualization of this pathway and save to file. This method generates a flowchart diagram showing all states, transitions, and branching logic using pure HTML/CSS. The visualization includes: - color-coded boxes based on state type (collect, tool, decision, summary) - clear flow arrows showing progression - reconvergence indicators for states with multiple parents - professional styling with hover effects Parameters ---------- title Title for the visualization page. If `None`, uses the pathway title. filename Name for the HTML file (without extension). If `None`, uses "pathway_visualization". auto_open Whether to automatically open the visualization in the default browser. Returns ------- str Path to the generated HTML file Examples -------- Create and display a pathway visualization: ```python import talk_box as tb # Create a pathway pathway = ( tb.Pathways( title="Customer Support", desc="Handle customer inquiries efficiently" ) .state("intake: gather customer information") .next_state("triage") .state("triage: determine support type") .branch_on("Technical issue", id="tech_support") .branch_on("Billing question", id="billing") .state("tech_support: resolve technical problems") .tools(["diagnostic_tool"]) .next_state("completion") .state("billing: handle billing inquiries") .next_state("completion") .state("completion: wrap up and follow up", type="summary") ) # Generate and open visualization pathway.visualize() # Opens in browser automatically # Save to specific file without opening pathway.visualize(filename="my_pathway", auto_open=False) ``` ## Conversation Methods Methods for managing conversation history add_message(self, content: str, role: str, metadata: Optional[dict[str, Any]] = None) -> talk_box.conversation.Message Append a message with the given role to the conversation. Creates a new `Message` object, assigns a unique ID and timestamp, and appends it to the internal message list. This is the low-level method underlying the role-specific convenience methods (`add_user_message`, `add_assistant_message`, `add_system_message`). Parameters ---------- content The text content of the message. role The role of the sender (e.g., `"user"`, `"assistant"`, `"system"`). metadata Optional dictionary of extra data to attach to the message. Returns ------- Message The newly created `Message` instance. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() msg = convo.add_message("Hello!", "user") msg.role ``` add_user_message(self, content: str, metadata: Optional[dict[str, Any]] = None) -> talk_box.conversation.Message Add a user-role message to the conversation. Convenience wrapper around `add_message()` with `role="user"`. Parameters ---------- content The text content of the message. metadata Optional dictionary of extra data to attach to the message. Returns ------- Message The newly created `Message` instance. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() msg = convo.add_user_message("What is Python?") msg.content ``` add_assistant_message(self, content: str, metadata: Optional[dict[str, Any]] = None) -> talk_box.conversation.Message Add an assistant-role message to the conversation. Convenience wrapper around `add_message()` with `role="assistant"`. Parameters ---------- content The text content of the message. metadata Optional dictionary of extra data to attach to the message. Returns ------- Message The newly created `Message` instance. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() msg = convo.add_assistant_message("Python is a programming language.") msg.role ``` add_system_message(self, content: str, metadata: Optional[dict[str, Any]] = None) -> talk_box.conversation.Message Add a system-role message to the conversation. Convenience wrapper around `add_message()` with `role="system"`. Parameters ---------- content The text content of the message. metadata Optional dictionary of extra data to attach to the message. Returns ------- Message The newly created `Message` instance. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() msg = convo.add_system_message("You are a helpful assistant.") msg.role ``` get_messages(self, role: Optional[str] = None) -> list[talk_box.conversation.Message] Return messages, optionally filtered by role. Returns a shallow copy of the internal message list so that callers can iterate or slice freely without mutating conversation state. Parameters ---------- role When provided, only messages matching this role are returned. When `None` (the default), all messages are returned. Returns ------- list[Message] A list of matching `Message` objects (copy of the internal list). Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() convo.add_user_message("Hi") convo.add_assistant_message("Hello!") len(convo.get_messages(role="user")) ``` get_last_message(self, role: Optional[str] = None) -> Optional[talk_box.conversation.Message] Return the most recent message, optionally filtered by role. Useful for quickly inspecting the latest assistant response or checking what the user last said without iterating the full history. Parameters ---------- role When provided, returns the last message with this role. When `None`, returns the last message regardless of role. Returns ------- Message | None The last matching message, or `None` if the conversation is empty (or no messages match the given role). Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() convo.add_user_message("First") convo.add_assistant_message("Second") convo.get_last_message().content ``` clear_messages(self) -> None Remove all messages from the conversation. Resets the message history to an empty state while preserving the conversation ID, metadata, and context window settings. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() convo.add_user_message("Hello") convo.clear_messages() convo.get_message_count() ``` set_context_window(self, max_length: int) -> None Limit how many recent messages `get_context_messages()` returns. When working with LLMs that have limited context, setting a window ensures only the most recent messages are sent, keeping token usage under control while preserving conversational continuity. Parameters ---------- max_length The maximum number of messages to include in the context window. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() for i in range(10): convo.add_user_message(f"Message {i}") convo.set_context_window(3) len(convo.get_context_messages()) ``` get_context_messages(self) -> list[talk_box.conversation.Message] Return messages within the configured context window. If no context window has been set, all messages are returned. Otherwise only the most recent `max_length` messages are included. Returns ------- list[Message] The messages within the context window. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() for i in range(5): convo.add_user_message(f"Msg {i}") convo.set_context_window(2) [m.content for m in convo.get_context_messages()] ``` get_message_count(self) -> int Return the total number of messages in the conversation. Equivalent to `len(conversation)` but available as an explicit method for discoverability in the API reference. Returns ------- int The message count. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() convo.add_user_message("Hi") convo.add_assistant_message("Hello!") convo.get_message_count() ``` to_dict(self) -> dict[str, typing.Any] Serialize the conversation to a plain dictionary. The output is JSON-serializable and can be persisted or transmitted. Use `from_dict()` to reconstruct the conversation later. Returns ------- dict[str, Any] Dictionary with keys `"conversation_id"`, `"created_at"`, `"metadata"`, `"max_context_length"`, and `"messages"`. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() convo.add_user_message("Test") d = convo.to_dict() list(d.keys()) ``` from_dict(data: dict[str, typing.Any]) -> 'Conversation' Reconstruct a conversation from a dictionary produced by `to_dict()`. Parameters ---------- data A dictionary with the structure produced by `to_dict()`. Returns ------- Conversation A fully restored conversation with all messages and metadata. Examples -------- ```{python} from talk_box.conversation import Conversation convo = Conversation() convo.add_user_message("Saved message") restored = Conversation.from_dict(convo.to_dict()) restored.get_message_count() ``` ## File Attachments Multi-modal file handling for conversations Attachments(*file_paths: Union[str, pathlib.Path]) File attachment handler for Talk Box conversations. The Attachments class enables you to include files in your AI conversations for analysis, review, and discussion. It automatically handles different file types (text, images, PDFs) and integrates seamlessly with `ChatBot` for programmatic conversations. **Primary Use Cases:** - **Code Review**: attach source files for automated code analysis - **Document Analysis**: process PDFs, reports, and documentation - **Data Analysis**: include CSV, JSON, or other data files for insights - **Content Generation**: attach references for context-aware content creation - **Image Analysis**: process diagrams, charts, or photos with vision models - **Research Assistance**: attach papers, articles, or research materials **Key Features:** - multi-file support with automatic content type detection - rich metadata collection for debugging and analytics - seamless ChatBot integration for programmatic workflows - chainable API following Talk Box design patterns - error handling with graceful fallbacks Parameters ---------- *file_paths Variable number of file paths to attach to the conversation. Examples -------- **Single File Analysis** ```python import talk_box as tb # Analyze a single document files = tb.Attachments("quarterly_report.pdf").with_prompt( "Summarize the key financial metrics and trends in this report." ) bot = tb.ChatBot().provider_model("openai:gpt-4-turbo") analysis = bot.chat(files) ``` **Code Review Workflow** ```python # Review multiple source files code_files = tb.Attachments( "src/main.py", "src/utils.py", "tests/test_main.py" ).with_prompt( "Review this Python code for bugs, performance issues, and best practices. " "Focus on the main logic and test coverage." ) reviewer = ( tb.ChatBot() .provider_model("openai:gpt-4-turbo") .preset("technical_advisor") .temperature(0.3) ) review = reviewer.chat(code_files) ``` **Data Analysis Pipeline** ```python # Analyze data files with context data_analysis = tb.Attachments( "sales_data.csv", "customer_segments.json", "analysis_notes.md" ).with_prompt( "Analyze the sales trends, identify top customer segments, " "and suggest actionable insights based on the data and notes provided." ) analyst = ( tb.ChatBot() .provider_model("openai:gpt-4-turbo") .temperature(0.4) .max_tokens(2000) ) insights = analyst.chat(data_analysis) ``` **Image and Document Combination** ```python # Combine visual and textual content presentation_review = ( tb.Attachments( "slide_deck.pdf", "speaker_notes.md", "chart_image.png" ).with_prompt( "Review this presentation for clarity, visual impact, and alignment " "between slides and speaker notes. Suggest improvements." ) ) presentation_bot = tb.ChatBot().provider_model("openai:gpt-4-turbo") feedback = presentation_bot.chat(presentation_review) ``` **Batch Processing Multiple Files** ```python # Process multiple documents for comparison for file_path in ["doc1.pdf", "doc2.pdf", "doc3.pdf"]: analysis = tb.Attachments(file_path).with_prompt( "Extract the main thesis and key arguments from this document." ) result = bot.chat(analysis) print(f"Analysis of {file_path}:") print(result) ``` **Jupyter Notebook Integration** ```python # HTML display in Jupyter notebooks files = tb.Attachments("code.py", "data.csv", "report.pdf").with_prompt( "Analyze these project files for insights and recommendations." ) # Just displaying the object shows an HTML summary files # Displays file count, sizes, types, and prompt in formatted HTML ``` ```python # Then process with ChatBot bot = tb.ChatBot().provider_model("openai:gpt-4-turbo") result = bot.chat(files) ``` The result here can also be displayed with HTML formatting: ```python result ``` Notes ----- - file attachments are designed for **single-turn programmatic conversations** - for interactive multi-turn conversations, use `bot.show("browser")` instead - large files are automatically chunked and processed efficiently - unsupported file types are handled gracefully with informative errors - all file processing includes timing and error metadata for debugging - **HTML representation**: displays rich summary in Jupyter notebooks so just print the object! with_prompt(self, prompt: str) -> 'Attachments' Add a text prompt to accompany the file attachments. This method enables the fluent interface for combining prompt text with file attachments, following Talk Box's chainable API design. The prompt provides context and instructions for how the AI should analyze or interact with the attached files. Parameters ---------- prompt The text prompt to include with the file attachments. This should provide clear instructions about what you want the AI to do with the attached files. Returns ------- Attachments Returns self for method chaining. Examples -------- **Specific Analysis Request** ```python import talk_box as tb files = ( tb.Attachments("financial_report.pdf") .with_prompt( "Extract the key financial metrics and identify any concerning trends " "in this quarterly report. Focus on revenue, profit margins, and cash flow." ) ) ``` **Code Review with Specific Criteria** ```python code_review = tb.Attachments("src/main.py", "tests/test_main.py").with_prompt( "Review this Python code for: " "1. Code quality and best practices " "2. Potential bugs or security issues " "3. Test coverage and completeness " "4. Performance optimization opportunities" ) ``` **Creative Content Generation** ```python references = ( tb.Attachments("brand_guide.pdf", "competitor_analysis.md") .with_prompt( "Based on our brand guidelines and competitor analysis, create a " "marketing strategy for our new product launch. Focus on differentiation " "and brand consistency." ) ) ``` **Data Analysis with Context** ```python data_files = ( tb.Attachments("sales_data.csv", "market_context.md") .with_prompt( "Analyze the sales data in the context of the market information provided. " "Identify trends, anomalies, and actionable insights for the sales team." ) ) ``` **Multi-file Comparison** ```python comparison = ( tb.Attachments("version1.py", "version2.py") .with_prompt( "Compare these two versions of the code and explain: " "- What changed between versions " "- Whether the changes improve or degrade the code " "- Any potential issues introduced" ) ) ``` Notes ----- - the prompt is combined with file content when sent to the AI model - clear, specific prompts lead to better analysis results - you can include formatting instructions (bullets, sections, etc.) - the prompt applies to all attached files collectively to_chat_contents(self) -> List[Any] Convert attachments to chatlas-compatible content list. This method processes all attached files and converts them into the appropriate chatlas content objects. Images become ContentImageInline objects, PDFs become ContentPDF objects, and text files are combined into the prompt text. Returns ------- List[Any] List containing text prompt and Content objects ready to pass directly to chatlas Chat.chat() method. Examples -------- ```python import talk_box as tb files = tb.Attachments("image.png", "doc.pdf").with_prompt("Analyze these") contents = files.to_chat_contents() # Result: ["Analyze these", ContentImageInline(...), ContentPDF(...)] ``` get_metadata(self) -> List[talk_box.attachments.AttachmentMetadata] Get metadata for all processed attachments. This method returns detailed metadata about file processing results, including timing information, file sizes, and any errors encountered. Useful for debugging, analytics, and user feedback. Returns ------- List[AttachmentMetadata] List of metadata objects, one per file processed. summary(self) -> str Get a human-readable summary of attached files. Creates a concise summary showing the number of files, total size, and breakdown by content type. Useful for logging, user interfaces, and debugging. Returns ------- str Formatted summary string like "📎 2/3 files attached (1.2MB): 1 image, 1 pdf [1 failed]" Examples -------- ```python import talk_box as tb files = tb.Attachments("code.py", "missing.txt", "diagram.png") print(files.summary()) # Output: "📎 2/3 files attached (15.2KB): 1 text, 1 image [1 failed]" ``` AttachmentMetadata(filename: str, file_type: str, size_bytes: int, content_type: str, processing_time_ms: Optional[float] = None, error: Optional[str] = None) -> None Metadata for individual file attachments. This class captures essential information about file processing results, enabling debugging, performance monitoring, and analytics for file attachment workflows. The metadata is automatically collected during file processing and can be accessed via the `Attachments.metadata` property for inspection and logging. Parameters ---------- filename The name of the file (without path). file_type File extension without the dot (e.g., 'pdf', 'png', 'py'). size_bytes File size in bytes. content_type Category of content: 'image', 'pdf', 'text', 'error', 'unsupported'. processing_time_ms Time taken to process the file in milliseconds. error Error message if processing failed. Examples -------- **Accessing File Metadata** ```python import talk_box as tb files = tb.Attachments("report.pdf", "image.png", "data.csv") # Process files (happens automatically during chat) bot = tb.ChatBot().provider_model("openai:gpt-4-turbo") conversation = bot.chat(files.with_prompt("Analyze these files")) # Inspect metadata for meta in files.metadata: print(f"File: {meta.filename}") print(f"Type: {meta.content_type}") print(f"Size: {meta.size_bytes:,} bytes") print(f"Processing time: {meta.processing_time_ms:.1f}ms") if meta.error: print(f"Error: {meta.error}") print("---") ``` **Performance Monitoring** ```python # Monitor processing performance for optimization large_files = tb.Attachments("big_report.pdf", "large_image.png") # ... process files ... total_time = sum(m.processing_time_ms for m in large_files.metadata) total_size = sum(m.size_bytes for m in large_files.metadata) print(f"Processed {len(large_files.metadata)} files") print(f"Total size: {total_size:,} bytes") print(f"Total time: {total_time:.1f}ms") print(f"Avg speed: {total_size/total_time*1000:.0f} bytes/sec") ``` **Error Detection and Handling** ```python files = tb.Attachments("good_file.pdf", "missing_file.txt", "corrupted.png") # ... process files ... # Check for errors failed_files = [m for m in files.metadata if m.error] successful_files = [m for m in files.metadata if not m.error] print(f"Successfully processed: {len(successful_files)} files") if failed_files: print("Failed files:") for meta in failed_files: print(f" {meta.filename}: {meta.error}") ``` ## Tools Tool registration, execution, and built-in utilities tool(_func: 'Optional[F]' = None, *, name: 'Optional[str]' = None, description: 'Optional[str]' = None, category: 'ToolCategory' = , examples: 'Optional[List[str]]' = None, requires_confirmation: 'bool' = False, timeout_seconds: 'Optional[float]' = None, max_retries: 'int' = 0, tags: 'Optional[List[str]]' = None, registry: 'Optional[ToolRegistry]' = None) -> 'Callable[[F], F]' Register a function as a Talk Box tool. Use `@tool` as a decorator on any function to make it available to `ChatBot` conversations and the `ToolRegistry`. The decorator supports two forms: bare (`@tb.tool`) and with keyword arguments (`@tb.tool(description="...")`). Parameters ---------- _func Internal parameter that captures the decorated function when the decorator is used without parentheses. Do not pass this explicitly. name Display name for the tool. Defaults to the function name. description Human-readable description shown to the LLM when it decides which tool to call. Defaults to the function's docstring. category A `ToolCategory` value used for filtering and dashboard display. Defaults to `ToolCategory.CUSTOM`. examples Optional list of example invocation strings for documentation. requires_confirmation If `True`, the tool will ask the user for confirmation before executing. Defaults to `False`. timeout_seconds Maximum wall-clock time (in seconds) before the tool execution is cancelled. `None` means no limit. max_retries Number of automatic retries on failure. Defaults to `0`. tags Freeform string tags for discovery and filtering. registry A `ToolRegistry` to register the tool in. Defaults to the global registry returned by `get_global_registry()`. Returns ------- Callable The original function, with a `_talk_box_tool` attribute attached. Examples -------- Register a tool with keyword arguments: ```python import talk_box as tb @tb.tool(description="Add two numbers", category=tb.ToolCategory.DATA) def add(x: int, y: int) -> int: return x + y ``` Register a tool without arguments (bare decorator): ```python @tb.tool def greet(name: str) -> str: return f"Hello, {name}!" ``` %seealso ToolCategory, ToolContext, ToolResult, get_global_registry ToolCategory(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Categorize tools by their primary function. Every tool registered with the `@tool` decorator belongs to exactly one category. Categories drive filtering in `ToolRegistry.get_tools_by_category()` and appear in debugging dashboards, so choosing the right category helps users discover and organize their tools. Values ------ - `WEB`: tools that make HTTP requests or interact with web APIs - `FILE`: tools that read, write, or transform files on disk - `DATA`: tools that query databases, transform datasets, or compute metrics - `COMMUNICATION`: tools that send emails, messages, or notifications - `SYSTEM`: tools that interact with the operating system or shell - `CUSTOM`: catch-all for tools that do not fit another category (the default) - `ANALYSIS`: tools that perform analysis, summarization, or inference - `SEARCH`: tools that search indexes, documents, or knowledge bases Examples -------- Pass a category when registering a tool: ```python import talk_box as tb @tb.tool(category=tb.ToolCategory.WEB) def fetch_page(url: str) -> str: ... ``` Filter registered tools by category: ```python registry = tb.get_global_registry() web_tools = registry.get_tools_by_category(tb.ToolCategory.WEB) ``` %seealso tool, ToolContext, ToolResult ToolContext(conversation_id: 'Optional[str]' = None, user_id: 'Optional[str]' = None, session_id: 'Optional[str]' = None, conversation_history: 'Optional[List[Dict[str, Any]]]' = None, user_metadata: 'Optional[Dict[str, Any]]' = None, tool_registry: "Optional['ToolRegistry']" = None, extra: 'Optional[Dict[str, Any]]' = None) Provide runtime context to every tool execution. When a tool is invoked, Talk Box creates a `ToolContext` and passes it as the first positional argument. The context carries conversation history, user metadata, and a reference to the `ToolRegistry`, giving the tool everything it needs to make informed decisions without accepting extra parameters from the caller. Parameters ---------- conversation_id Identifier for the current conversation. Useful for correlating tool calls with conversation logs. user_id Identifier for the user who triggered the tool call. session_id Identifier for the broader session (may span multiple conversations). conversation_history List of message dictionaries from the current conversation. Each dictionary contains at minimum `"role"` and `"content"` keys. user_metadata Arbitrary metadata about the user (preferences, permissions, etc.). tool_registry The `ToolRegistry` instance that the tool belongs to. Allows tools to discover and invoke other tools at runtime. extra Open-ended dictionary for passing additional data that does not fit the other fields. Examples -------- Create a context manually (most often done by `ToolEnabledConversation`): ```python from talk_box.tools import ToolContext ctx = ToolContext( conversation_id="conv-42", user_id="user-7", conversation_history=[ {"role": "user", "content": "What's the weather?"} ], ) ctx.get_last_messages(1) ``` %seealso ToolResult, ToolCategory, ToolEnabledConversation ToolResult(data: 'Any', success: 'bool' = True, error: 'Optional[str]' = None, metadata: 'Optional[Dict[str, Any]]' = None, display_format: 'str' = 'auto', should_continue: 'bool' = True, confidence: 'Optional[float]' = None, sources: 'Optional[List[str]]' = None, extra: 'Optional[Dict[str, Any]]' = None) Represent the outcome of a tool execution. Every tool returns a `ToolResult` (or Talk Box wraps the return value in one). The object carries the primary data, success/failure status, optional metadata such as confidence scores and source citations, and a display format hint that controls how the result is rendered in conversations. Parameters ---------- data The primary return value of the tool. Can be any serializable type. success Whether the tool executed without errors. Defaults to `True`. error A human-readable error message when `success` is `False`. metadata Arbitrary key-value pairs for downstream consumers (analytics, logging, etc.). display_format Hint for how to render the result in a conversation. One of `"auto"`, `"json"`, `"text"`, `"html"`, or `"markdown"`. Defaults to `"auto"`. should_continue Whether the conversation should continue after this tool result. Set to `False` to signal that the tool's output is terminal. Defaults to `True`. confidence Optional float between 0 and 1 indicating how confident the tool is in its result. sources Optional list of source URLs or identifiers that back the result. extra Open-ended dictionary for additional data. Examples -------- Return a successful result from a tool function: ```python from talk_box.tools import ToolResult result = ToolResult(data={"temperature": 72, "unit": "F"}, confidence=0.95) result.success ``` Signal an error: ```python err = ToolResult(data=None, success=False, error="API key expired") err.success ``` %seealso ToolContext, tool, ToolCategory get_global_registry() -> 'ToolRegistry' Return the process-wide `ToolRegistry` singleton. All `@tool`-decorated functions are registered here by default. Use this function when you need to inspect, iterate, or pass the registry to other components such as `ToolEnabledConversation` or `ChatBot`. Returns ------- ToolRegistry The global registry instance. Examples -------- ```python import talk_box as tb registry = tb.get_global_registry() all_tools = registry.get_all_tools() ``` %seealso tool, ToolEnabledConversation load_tool_box() Register all built-in Tool Box tools in the global registry. Call this once at startup to make every built-in tool (text processing, math, date/time, data utilities, web helpers, file tools) available to `ChatBot` and `ToolEnabledConversation`. If the tools are already registered (e.g., from a previous call) the function is a no-op. Returns ------- int The number of built-in tools now present in the global registry. Examples -------- ```python import talk_box as tb count = tb.load_tool_box() ``` %seealso get_builtin_tool, load_selected_tools, get_global_registry get_builtin_tool(name: str) Get a specific built-in tool by name. This allows cherry-picking individual tools from the Tool Box rather than loading all tools with load_tool_box(). The tool will be automatically loaded into the registry if it's not already there. Parameters ---------- name : str Name of the tool to retrieve Returns ------- TalkBoxTool The requested tool Examples -------- >>> calculate_tool = get_builtin_tool("calculate") >>> email_tool = get_builtin_tool("validate_email") load_selected_tools(tool_names: List[str]) -> None Register a subset of the built-in Tool Box tools. This provides a middle ground between loading every built-in tool with `load_tool_box()` and fetching them one at a time with `get_builtin_tool()`. Each requested tool is validated, registered in the global registry, and ready for use. Parameters ---------- tool_names Names of the built-in tools to load. Raises ------ ValueError If any name in `tool_names` does not match a known built-in tool. Examples -------- ```python import talk_box as tb tb.load_selected_tools(["text_stats", "calculate", "convert_case"]) ``` %seealso load_tool_box, get_builtin_tool ## Testing & Validation Automated testing for chatbot quality assurance autotest_avoid_topics(target_bot, test_intensity: str = 'medium', max_conversations: int = None, judge_model=None, verbose: bool = False) -> 'TestResults' Comprehensive avoid topics testing with automated violation detection. This function runs adversarial testing using QuestionProducerBot prompts and automatically evaluates responses using the enhanced JudgeBot to detect violations. It combines prompt generation, conversation testing, and violation analysis into a single, easy-to-use interface for comprehensive compliance validation. **Testing Framework**: The function orchestrates a sophisticated testing pipeline that generates adversarial questions targeting configured avoid topics, conducts conversations with the target bot, and automatically evaluates responses for violations using structured evaluation criteria. This provides automated compliance testing with detailed analysis. **Automated Evaluation**: Uses JudgeBot with PromptBuilder to systematically analyze bot responses for avoid topics violations, providing severity ratings, specific quotes, and detailed explanations. The evaluation is consistent and objective, removing human bias from compliance assessment. **Rich Reporting**: Returns TestResults with comprehensive violation analysis, conversation transcripts, statistical summaries, and HTML representation for Jupyter notebooks. Results include export capabilities for further analysis and integration with quality assurance workflows. Parameters ---------- target_bot The ChatBot instance to test for avoid topics compliance. Must have avoid topics configured via the `.avoid()` method or `PromptBuilder.avoid_topics()` in system prompt. test_intensity Testing intensity level controlling number of conversations and strategies. Available levels: `"minimal"` (1 conversation), `"light"` (3 conversations), `"medium"` (6 conversations), `"thorough"` (10 conversations), `"exhaustive"` (15 conversations). The default is `"medium"`. max_conversations Override for maximum number of conversations to run, superseding the intensity level setting. Use when you need precise control over test scope. judge_model Model to use for automated judgment. If provided, will be set via `.model()` on the `JudgeBot`. Defaults to inheriting model configuration from `target_bot=` for consistency. verbose Whether to show detailed output during testing including conversation progress and intermediate results. Default is `False` for clean output. Returns ------- TestResults Enhanced results object with rich reporting capabilities including individual conversation results with violation analysis, automated violation detection with severity ratings, statistical summaries and compliance metrics, HTML representation for Jupyter notebooks, and export capabilities for further analysis. Examples -------- ### Basic avoid topics testing Test a bot with a simple avoid topics configuration: ```python import talk_box as tb # Configure bot with avoid topics bot = ( tb.ChatBot() .provider_model("openai:gpt-4-turbo") .avoid(["medical_advice", "financial_planning"] ) # Run basic compliance testing results = tb.autotest_avoid_topics(bot, test_intensity="light") # Check compliance results print(f"Compliance rate: {results.summary['compliance_rate']:.1%}") print(f"Violations found: {results.summary['total_violations']}") ``` View HTML-based summary of results: ```python results ``` ### Testing with PromptBuilder configuration Test a bot configured with `PromptBuilder` avoid topics: ```python import talk_box as tb # Configure bot with `PromptBuilder` prompt = ( tb.PromptBuilder() .persona("helpful assistant", "general support") .avoid_topics(["politics", "religion"]) .constraint("Always be respectful and professional") ) bot = tb.ChatBot().provider_model("openai:gpt-4-turbo").system_prompt(prompt) # Run thorough testing results = tb.autotest_avoid_topics(bot, test_intensity="thorough") # Display detailed violation analysis results.show_violations() ``` ### Advanced testing with custom configuration Comprehensive testing with custom judge model and verbose output: ```python import talk_box as tb # Configure specialized bot bot = ( tb.ChatBot() .model("gpt-4") .avoid(["legal_advice", "investment_recommendations"]) .temperature(0.3) .persona("customer service representative") ) # Run comprehensive testing with custom judge results = tb.autotest_avoid_topics( bot, test_intensity="exhaustive", judge_model="gpt-4", verbose=True ) # Analyze results comprehensively print(f"Total conversations: {len(results.conversation_results)}") print(f"Compliance rate: {results.summary['compliance_rate']:.1%}") # Export results for further analysis if results.summary['total_violations'] > 0: violation_details = results.get_violation_summary() print("Violations requiring attention:") for violation in violation_details: print(f"- {violation['topic']}: {violation['severity']}") # HTML display in notebooks results ``` Integration Notes ----------------- - **Avoid Topics Detection**: automatically extracts avoid topics from bot configuration or system prompt - **Intensity Scaling**: different intensity levels provide appropriate testing coverage for various use cases - **Automated Evaluation**: judgeBot provides consistent, objective violation detection with detailed analysis - **Rich Reporting**: `TestResults` includes comprehensive analysis, visualizations, and export capabilities - **Quality Assurance**: enables systematic compliance testing as part of development and deployment workflows - **Professional Integration**: results format supports integration with quality assurance and compliance systems The `autotest_avoid_topics()` function provides comprehensive automated testing for avoid topics compliance, enabling systematic validation of chatbot behavior with detailed analysis and reporting capabilities suitable for professional development and deployment workflows. autotest_pathways(target_bot, test_intensity: str = 'medium', max_tests: int = None, judge_model: str = None, verbose: bool = False) -> 'PathwayTestResults' Automated testing for pathway adherence in chatbots. This function tests whether a chatbot properly follows defined conversational pathways, gathering required information and progressing through expected states while maintaining flexibility for natural conversation flow. **Comprehensive Testing Framework**: The function orchestrates sophisticated pathway testing that generates realistic user scenarios designed to test pathway boundaries, information gathering requirements, state transitions, and adherence to conversation flow logic. This provides automated pathway compliance testing with detailed analysis. **Multi-Strategy Adversarial Testing**: Uses multiple testing strategies including cooperative flows, state-skipping attempts, backtracking scenarios, incomplete information provision, tangential conversations, resistance to structured approaches, and edge case boundary testing. Each strategy is designed to probe different aspects of pathway adherence. **Automated Evaluation**: Uses PathwayJudgeBot with PromptBuilder to systematically analyze conversations for pathway adherence, providing adherence scores, state progression tracking, information gathering assessment, and detailed explanations. The evaluation is consistent and objective, removing human bias from pathway compliance assessment. **Rich Reporting**: Returns PathwayTestResults with comprehensive pathway analysis, conversation transcripts, adherence scores, statistical summaries, and HTML representation for Jupyter notebooks. Results include export capabilities for further analysis and integration with quality assurance workflows. Parameters ---------- target_bot The ChatBot instance to test for pathway adherence. Must have pathways configured in its system prompt via PromptBuilder.pathways() or equivalent. test_intensity : str, default "medium" Testing intensity level controlling number of tests and strategies. Available levels: "minimal" (2 tests), "light" (6 tests), "medium" (12 tests), "thorough" (20 tests), "exhaustive" (30 tests). max_tests : int, optional Override for maximum number of tests to run, superseding the intensity level setting. Use when you need precise control over test scope. judge_model : str, optional Model to use for automated pathway adherence evaluation. If provided, will be used for the PathwayJudgeBot. Defaults to inheriting model configuration from target_bot for consistency. verbose : bool, default False Whether to show detailed output during testing including test progress and intermediate results. Default is False for clean output. Requirements ------------ **API Access**: This function requires valid API credentials for either OpenAI or Anthropic services. Set the OPENAI_API_KEY or ANTHROPIC_API_KEY environment variable. Without API access, the function will complete but return empty results with 0 tests. Returns ------- PathwayTestResults Enhanced results object with rich reporting capabilities including individual test results with pathway analysis, automated adherence evaluation with detailed scoring, statistical summaries and compliance metrics, HTML representation for Jupyter notebooks, and export capabilities for further analysis. Examples -------- ### Basic pathway testing Test a bot with a simple pathway configuration: ```python import talk_box as tb # Create pathway support_pathway = ( tb.Pathways( title="Customer Support", desc="systematic customer assistance", activation="Customer needs help with an issue" ) .state("intake: gather issue details") .required(["problem description", "contact info"]) .next_state("resolution") .state("resolution: provide solution") .success_condition("customer issue is resolved") ) # Configure bot with pathway bot = ( tb.ChatBot() .provider_model("openai:gpt-4-turbo") .system_prompt( tb.PromptBuilder() .persona("helpful support agent") .pathways(support_pathway) ) ) # Run basic pathway testing results = tb.autotest_pathways(bot, test_intensity="light") # Check adherence results print(f"Average adherence: {results.summary['avg_adherence_score']:.1%}") print(f"Tests completed: {results.summary['total_tests']}") ``` ### Advanced testing with custom configuration Comprehensive testing with custom judge model and verbose output: ```python import talk_box as tb # Configure specialized bot with complex pathway onboarding_pathway = ( tb.Pathways( title="User Onboarding", desc="comprehensive new user setup process", activation=["new user registration", "account setup needed"] ) .state("welcome: introduce platform") .next_state("profile_setup") .state("profile_setup: collect user information") .required(["name", "email", "role"]) .branch_on("business user", id="business_setup") .branch_on("individual user", id="personal_setup") .state("business_setup: configure business features") .next_state("completion") .state("personal_setup: configure personal preferences") .next_state("completion") .state("completion: finalize setup") .success_condition("user account is fully configured") ) bot = ( tb.ChatBot() .provider_model("openai:gpt-4-turbo") .system_prompt( tb.PromptBuilder() .persona("friendly onboarding specialist") .pathways(onboarding_pathway) .final_emphasis("Follow pathway while being conversational") ) .temperature(0.3) ) # Run comprehensive testing with custom judge results = tb.autotest_pathways( bot, test_intensity="thorough", judge_model="openai:gpt-4", verbose=True ) # Analyze results comprehensively print(f"Total tests: {len(results.results)}") print(f"Average adherence: {results.summary['avg_adherence_score']:.1%}") print(f"State progression coverage: {results.summary['state_coverage']:.1%}") # Export results for further analysis if results.summary['avg_adherence_score'] < 0.8: problem_areas = results.get_problem_summary() print("Areas needing attention:") for area in problem_areas: print(f"- {area['issue']}: {area['frequency']} occurrences") # HTML display in notebooks results ``` Integration Notes ----------------- - **Pathway Detection**: automatically extracts pathway specifications from bot configuration or system prompt - **Intensity Scaling**: different intensity levels provide appropriate testing coverage for various use cases from development to production validation - **Automated Evaluation**: PathwayJudgeBot provides consistent, objective adherence analysis with detailed scoring - **Rich Reporting**: PathwayTestResults includes comprehensive analysis, visualizations, and export capabilities - **Quality Assurance**: enables systematic pathway compliance testing as part of development and deployment workflows - **Professional Integration**: results format supports integration with quality assurance and compliance systems The autotest_pathways() function provides comprehensive automated testing for pathway adherence, enabling systematic validation of conversation flow behavior with detailed analysis and reporting capabilities suitable for professional development and deployment workflows. TestResults(results: List[talk_box.testing.ConversationResult], test_config: Dict[str, Any] = None, violation_records: List = None) Enhanced test results container with rich reporting and analysis capabilities. TestResults provides comprehensive analysis and reporting capabilities for avoid topics testing results, including interactive HTML representations, statistical summaries, violation analysis, and export functionality. The class is designed to support both programmatic analysis and interactive exploration in Jupyter notebooks and development environments. **Rich Reporting**: provides beautiful HTML representations optimized for Jupyter notebooks with interactive visualizations, summary statistics, and detailed violation analysis. The HTML output includes configuration details, compliance metrics, and conversation transcripts for comprehensive review. **Statistical Analysis**: Includes comprehensive summary statistics covering compliance rates, violation counts, topic and strategy breakdowns, timing analysis, and success metrics. Summary data supports both quick overview and detailed performance analysis. **Export Capabilities**: Supports export to pandas DataFrames and Great Tables for further analysis, reporting, and integration with data science workflows. Export functions handle optional dependencies gracefully with clear error messages. **Interactive Access**: Implements standard Python container protocols (iteration, indexing, length) for easy programmatic access to individual conversation results while maintaining the reporting capabilities for interactive use. Parameters ---------- results List of ConversationResult objects containing individual test outcomes. Each result includes conversation details, violation information, timing data, and metadata from the testing process. test_config Dictionary containing test configuration parameters including intensity level, target bot configuration, testing strategies used, and other metadata from the testing session. Used for context in reporting. violation_records List of ViolationRecord objects containing detailed violation analysis from automated evaluation. Includes severity assessments, specific quotes, judge explanations, and violation metadata. Attributes ---------- results : List[ConversationResult] Individual conversation test results with full details test_config : Dict[str, Any] Testing configuration and metadata violation_records : List[ViolationRecord] Detailed violation analysis records summary : Dict[str, Any] Statistical summary of test results (property) Examples -------- ### Accessing TestResults attributes Work with the core attributes of TestResults: ```python import talk_box as tb # Run testing bot = tb.ChatBot().avoid(["medical_advice"]) results = tb.autotest_avoid_topics(bot, test_intensity="medium") # Access core attributes print(f"Individual results: {len(results.results)}") print(f"Test config: {results.test_config}") print(f"Violation records: {len(results.violation_records)}") # Iterate through conversation results for result in results.results: print(f"Topic: {result.topic}, Strategy: {result.strategy}") if result.violations: print(f" - Violations: {len(result.violations)}") ``` ### Using the summary property Access comprehensive test statistics: ```python import talk_box as tb bot = tb.ChatBot().avoid(["financial_advice", "legal_advice"]) results = tb.autotest_avoid_topics(bot, test_intensity="thorough") # Access summary statistics summary = results.summary print(f"Total tests: {summary['total_tests']}") print(f"Success rate: {summary['success_rate']:.1%}") print(f"Violations found: {summary['violation_count']}") print(f"Average duration: {summary['avg_duration']:.2f} seconds") print(f"Topics tested: {list(summary['topics_tested'].keys())}") print(f"Strategies used: {list(summary['strategies_used'].keys())}") ``` ### Container protocol usage Use TestResults as a Python container: ```python import talk_box as tb results = tb.autotest_avoid_topics(bot, test_intensity="medium") # Container-like access print(f"Total results: {len(results)}") first_result = results[0] print(f"First test: {first_result.topic} using {first_result.strategy}") # Iteration for i, result in enumerate(results): status = "PASSED" if result.completed and not result.violations else "FAILED" print(f"Test {i+1}: {result.topic} - {status}") # Find specific results violations = [r for r in results if r.violations] if violations: print(f"Found {len(violations)} tests with violations") ``` ### Export methods for data analysis Convert results to structured formats: ```python import talk_box as tb results = tb.autotest_avoid_topics(bot, test_intensity="exhaustive") # Export to pandas DataFrame df = results.to_dataframe() print("Violations by topic:") print(df.groupby('topic')['violations'].sum()) print(" Success rate by strategy:") success_by_strategy = df.groupby('strategy')['status'].apply( lambda x: (x == 'Passed').mean() ) print(success_by_strategy) # Create Great Tables report gt_table = results.to_great_table() gt_table.save("compliance_report.html") ``` Integration Notes ----------------- - **Container Protocol**: Implements `__len__`, `__iter__`, and `__getitem__` for standard Python container behavior - **Rich Display**: Automatic HTML rendering in Jupyter notebooks with interactive visualizations - **Export Flexibility**: Multiple export formats with graceful handling of optional dependencies - **Statistical Analysis**: Comprehensive metrics for compliance assessment and performance analysis - **Quality Assurance**: Designed for integration with automated testing and deployment workflows - **Violation Analysis**: Detailed violation tracking with severity assessment and explanatory context The TestResults class provides a comprehensive foundation for analyzing, reporting, and acting on avoid topics testing outcomes, supporting both interactive exploration and automated quality assurance processes in professional development workflows. to_dataframe(self) Convert test results to a pandas `DataFrame`. Each row represents one conversation test with columns for topic, strategy, completion status, violation count, duration, timestamp, and overall pass/fail status. Returns ------- pandas.DataFrame A DataFrame with one row per conversation result. Raises ------ ImportError If pandas is not installed. Examples -------- ```python import talk_box as tb results = tb.autotest_avoid_topics(bot, test_intensity="medium") df = results.to_dataframe() print(df.columns.tolist()) ``` to_great_table(self) Create a styled Great Tables report from the test results. Produces a `GT` table with a header, formatted numbers, color-coded pass/fail status, and bold column labels. Returns ------- great_tables.GT A configured Great Tables object ready for display or export. Raises ------ ImportError If great-tables is not installed. Examples -------- ```python import talk_box as tb results = tb.autotest_avoid_topics(bot, test_intensity="medium") table = results.to_great_table() table.save("report.html") ``` PathwayTestResults(test_results: List[talk_box.testing.PathwayTestResult], test_config: Dict[str, Any]) Aggregate and summarize the outcomes of a `autotest_pathways()` run. After `autotest_pathways()` exercises every pathway with the configured test strategies, it wraps the individual `PathwayTestResult` records and the test configuration into a `PathwayTestResults` object. Use this object to inspect pass rates, adherence scores, state coverage, and per-strategy breakdowns. Parameters ---------- test_results List of `PathwayTestResult` objects, one per individual test execution. test_config Dictionary describing how the test run was configured (pathway count, strategies, model, etc.). Examples -------- Run pathway tests and inspect results (requires an LLM provider): ```python import talk_box as tb pathways = tb.Pathways(title="Demo", desc="A demo pathway") # ... define states ... results = tb.autotest_pathways(pathways, model="openai") results.summary["completion_rate"] ``` %seealso autotest_pathways, Pathways, TestResults ToolEnabledConversation(conversation_id: Optional[str] = None, tool_registry: Optional[ForwardRef('ToolRegistry')] = None, auto_tools: bool = True, tool_confirmation: bool = False) Extend `Conversation` with automatic tool invocation support. `ToolEnabledConversation` inherits every feature of `Conversation` and adds the ability to discover, invoke, and record tool calls. When `auto_tools` is `True`, the conversation can automatically match user requests to registered tools and inject tool results back into the message history. Parameters ---------- conversation_id Optional identifier for this conversation. Generated automatically when `None`. tool_registry The `ToolRegistry` that holds available tools. When `None` the global registry returned by `get_global_registry()` is used. auto_tools If `True` (the default), the conversation may invoke tools automatically when a matching tool is found for a user message. tool_confirmation If `True`, prompt the user for confirmation before executing any tool. Defaults to `False`. Examples -------- Create a tool-enabled conversation and list available tools: ```python import talk_box as tb conv = tb.ToolEnabledConversation() conv.get_available_tools() ``` Use the convenience factory instead: ```python conv = tb.create_tool_conversation() ``` %seealso Conversation, create_tool_conversation, ToolContext create_tool_conversation() -> talk_box.conversation.ToolEnabledConversation Create a `ToolEnabledConversation` with default settings. This is a convenience factory that returns a new conversation backed by the global tool registry, with `auto_tools` enabled and `tool_confirmation` disabled. Returns ------- ToolEnabledConversation A ready-to-use conversation with tool support. Examples -------- ```python import talk_box as tb conv = tb.create_tool_conversation() conv.get_available_tools() ``` %seealso ToolEnabledConversation, Conversation ## Guardrails Composable input/output validation for chatbot messages Guard(name: 'str', func: 'Callable[[str], GuardResult]', phase: 'GuardPhase' = , states: 'list[str] | None' = None) -> None A configured guardrail ready to be attached to a ChatBot. Attributes ---------- name Human-readable guard name (used in telemetry and error messages). func The guard function: takes a string, returns a `GuardResult`. phase When this guard runs (input, output, or both). check(self, text: 'str') -> 'GuardResult' Run the guard against the given text. Parameters ---------- text Message text to validate. Returns ------- GuardResult The outcome with action, optional rewrite, and reason. GuardAction(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) The outcome of a guard check. GuardPhase(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) When the guard runs in the message lifecycle. GuardResult(action: 'GuardAction', message: 'Optional[str]' = None, reason: 'Optional[str]' = None, guard_name: 'Optional[str]' = None) -> None The result of evaluating a guardrail against a message. Use the class methods `passed()`, `blocked()`, and `rewrite()` to construct results rather than calling the constructor directly. Attributes ---------- action Whether the message passed, was blocked, or was rewritten. message The (possibly rewritten) message text. `None` when blocked. reason Human-readable explanation of why the guard acted. guard_name Name of the guard that produced this result. GuardPipeline() -> 'None' Ordered pipeline of guards that processes messages sequentially. Guards run in the order they were added. If a guard blocks, the pipeline stops immediately. If a guard rewrites, subsequent guards see the rewritten text. add(self, guard: 'Guard') -> 'None' Add a guard to the end of the pipeline. Parameters ---------- guard A configured `Guard` instance. run(self, text: 'str', phase: 'GuardPhase', *, current_state: 'str | None' = None) -> 'GuardPipelineResult' Run all applicable guards against the text. Parameters ---------- text The message text to validate. phase Current phase (`INPUT` or `OUTPUT`). Guards with matching phase or `BOTH` will run. current_state The current pathway state name. Guards with a ``states`` restriction are skipped when the state doesn't match. Returns ------- GuardPipelineResult The final text (possibly rewritten) and activation log. GuardPipelineResult(text: 'Optional[str]', blocked: 'bool' = False, block_reason: 'Optional[str]' = None, activations: 'list[GuardActivation]' = ) -> None Result of running a message through the full guard pipeline. Attributes ---------- text The final message text (original, rewritten, or None if blocked). blocked Whether the message was blocked by any guard. block_reason Reason for blocking (if blocked). activations Log of all guard activations in order. guardrail(func: 'Callable[[str], GuardResult] | None' = None, *, name: 'str | None' = None, phase: 'GuardPhase' = , states: 'list[str] | None' = None) -> 'Guard | Callable[[Callable[[str], GuardResult]], Guard]' Decorator that turns a function into a composable guardrail. Can be used as a bare decorator or with keyword arguments. Parameters ---------- func The guard function (when used as bare `@guardrail`). name Override the guard's display name (defaults to the function name). phase When to run: `"input"`, `"output"`, or `"both"` (default). states Optional list of pathway state names where this guard is active. When ``None`` (the default), the guard runs in all states. When set, the guard is skipped unless the current pathway state matches one of the listed names. Returns ------- Guard A configured guard instance. Examples -------- Bare decorator: ```python @tb.guardrail def no_profanity(text: str) -> tb.GuardResult: if any(w in text.lower() for w in BAD_WORDS): return tb.GuardResult.blocked("Profanity detected") return tb.GuardResult.passed() ``` With options: ```python @tb.guardrail(name="PII Filter", phase=GuardPhase.INPUT) def strip_emails(text: str) -> tb.GuardResult: cleaned = re.sub(r'\S+@\S+', '[EMAIL]', text) if cleaned != text: return tb.GuardResult.rewrite(cleaned, reason="Stripped email addresses") return tb.GuardResult.passed() ``` guardrail(self, guard: 'Guard') -> 'ChatBot' Add a guardrail to the chatbot's validation pipeline. Guards run in the order they are added. Input guards validate user messages before the LLM sees them. Output guards validate LLM responses before they are returned to the user. If any guard blocks a message, the pipeline short-circuits. Parameters ---------- guard A `Guard` instance, typically created by `@tb.guardrail`, or one of the built-in guard factories (`tb.no_pii()`, `tb.max_response_length()`, etc.). Returns ------- ChatBot The same instance for method chaining. Examples -------- ```python import talk_box as tb bot = ( tb.ChatBot() .guardrail(tb.no_pii()) .guardrail(tb.max_response_length(500)) .guardrail(tb.disclaimer_required("Not financial advice.")) ) ``` guard_stats(self) -> dict[str, dict[str, int]] Get activation statistics for all attached guardrails. Returns ------- dict[str, dict[str, int]] Mapping of guard name to counts of `passed`, `blocked`, and `rewritten` activations. Examples -------- ```python stats = bot.guard_stats() # {'no_pii': {'passed': 42, 'blocked': 0, 'rewritten': 3}, # 'max_response_length': {'passed': 40, 'blocked': 0, 'rewritten': 5}} ``` no_pii(*, patterns: 'list[str] | None' = None, action: 'str' = 'rewrite') -> 'Guard' Guard that detects and handles Personally Identifiable Information. Detects email addresses, phone numbers, SSNs, and credit card numbers by default. Can be extended with custom regex patterns. Parameters ---------- patterns Additional regex patterns to detect. Each should match PII strings. action What to do when PII is found: `"rewrite"` (replace with placeholders) or `"block"` (reject the message entirely). Returns ------- Guard A configured PII detection guard. Examples -------- ```python bot = tb.ChatBot().guardrail(tb.no_pii()) bot = tb.ChatBot().guardrail(tb.no_pii(action="block")) ``` max_response_length(max_chars: 'int') -> 'Guard' Guard that enforces a maximum response length. Truncates responses that exceed the character limit, appending an ellipsis to indicate truncation. Parameters ---------- max_chars Maximum allowed characters in the response. Returns ------- Guard A configured length enforcement guard (output-only). Examples -------- ```python bot = tb.ChatBot().guardrail(tb.max_response_length(500)) ``` max_input_length(max_chars: 'int') -> 'Guard' Guard that rejects user messages exceeding a character limit. Parameters ---------- max_chars Maximum allowed characters in the input message. Returns ------- Guard A configured input length guard (input-only). Examples -------- ```python bot = tb.ChatBot().guardrail(tb.max_input_length(10000)) ``` tone_check(expected_tone: 'str', *, indicators: 'dict[str, list[str]] | None' = None) -> 'Guard' Guard that flags responses not matching the expected tone. Uses keyword-based heuristics to detect tone mismatches. For production use with high accuracy, consider extending with an LLM-based judge. Parameters ---------- expected_tone The desired tone (e.g., `"professional"`, `"casual"`, `"formal"`). indicators Optional mapping of tone names to indicator words/phrases. If not provided, uses built-in defaults for common tones. Returns ------- Guard A configured tone-checking guard (output-only). Examples -------- ```python bot = tb.ChatBot().guardrail(tb.tone_check("professional")) ``` disclaimer_required(disclaimer_text: 'str', *, position: 'str' = 'end') -> 'Guard' Guard that ensures a required disclaimer appears in the response. If the disclaimer is missing, it is appended (or prepended) automatically. Parameters ---------- disclaimer_text The exact disclaimer text that must appear. position Where to add the disclaimer if missing: `"end"` (default) or `"start"`. Returns ------- Guard A configured disclaimer enforcement guard (output-only). Examples -------- ```python bot = tb.ChatBot().guardrail( tb.disclaimer_required("This is not financial advice.") ) ``` must_cite_sources(*, min_citations: 'int' = 1) -> 'Guard' Guard that requires responses to contain source citations. Detects common citation patterns: URLs, bracketed references, footnotes, and `Source:` labels. Parameters ---------- min_citations Minimum number of citation patterns required. Defaults to 1. Returns ------- Guard A configured citation enforcement guard (output-only). Examples -------- ```python bot = tb.ChatBot().guardrail(tb.must_cite_sources()) ``` keyword_block(keywords: 'list[str]', *, case_sensitive: 'bool' = False, phase: 'GuardPhase' = ) -> 'Guard' Guard that blocks messages containing any of the specified keywords. Parameters ---------- keywords List of words or phrases to block. case_sensitive Whether matching should be case-sensitive. phase When to apply: input, output, or both. Returns ------- Guard A configured keyword blocking guard. Examples -------- ```python bot = tb.ChatBot().guardrail( tb.keyword_block(["password", "secret key", "api_key"]) ) ``` ## Evaluation Prompt evaluation, scoring, and regression detection eval_regression(before: "'ChatBot'", after: "'ChatBot'", *, queries: 'list[str | EvalCase] | None' = None, dimensions: 'list[EvalDimension] | None' = None, judge: "str | 'ChatBot | None'" = None, threshold: 'float' = 0.05) -> 'EvalResults' Compare two bot versions and flag regressions. A convenience wrapper around `eval()` that runs both versions against the same queries and pre-computes regression analysis. Parameters ---------- before The baseline bot (e.g., current production version). after The new bot (e.g., with updated prompt or guardrails). queries Queries to evaluate. Falls back to persona test_queries. dimensions Scoring dimensions. Defaults to relevance, safety, instruction_adherence. judge Judge model string or ChatBot. threshold Score drop threshold to flag as a regression. Returns ------- EvalResults Results with regression analysis accessible via `.regressions()`. eval_model_update(persona: 'str', *, before: 'str', after: 'str', queries: 'list[str | EvalCase] | None' = None, dimensions: 'list[EvalDimension] | None' = None, judge: "str | 'ChatBot | None'" = None, threshold: 'float' = 0.05, default_guards: 'bool' = True, scorecard_path: 'str | Path | None' = None) -> 'EvalResults' Compare persona behavior across two model versions. A convenience wrapper around `eval_suite()` that builds two bot variants from the same persona (one per model string) and flags any dimensions where the newer model regresses compared to the older one. Parameters ---------- persona Persona name to evaluate (e.g., `"code_reviewer"`). before Provider:model string for the baseline model (e.g., `"anthropic:claude-sonnet-4-5"`). after Provider:model string for the new model (e.g., `"anthropic:claude-sonnet-4-6"`). queries Queries to evaluate. Falls back to persona `test_queries`. dimensions Scoring dimensions. Defaults to relevance, safety, instruction_adherence. judge Judge model string or ChatBot. threshold Score drop to flag as a regression (default 0.05 = 5%). default_guards Whether to apply persona default guards. scorecard_path If provided, writes the scorecard JSON to this path. Returns ------- EvalResults Results with two variants (named after the model strings). Use `.regressions(baseline=before, threshold=threshold)` to inspect dimension-level drops, or `.to_great_table()` / `.scorecard_table()` for a visual comparison. Raises ------ ValueError If `before=` and `after=` are the same string. Examples -------- ```python import talk_box as tb results = tb.eval_model_update( "code_reviewer", before="anthropic:claude-sonnet-4-5", after="anthropic:claude-sonnet-4-6", judge="anthropic:claude-sonnet-4-6", ) # Check for regressions drops = results.regressions() if drops: print("Regressions detected:", drops) # Visual comparison results.to_great_table() ``` eval_suite(persona: 'str', *, models: 'list[str]', queries: 'list[str | EvalCase] | None' = None, dimensions: 'list[EvalDimension] | None' = None, judge: "str | 'ChatBot | None'" = None, default_guards: 'bool' = True, scorecard_path: 'str | Path | None' = None) -> 'EvalResults' Evaluate a persona across multiple models (model comparison matrix). Creates a variant for each model, runs the persona's test queries (or explicit queries) through each one, scores with a judge, and returns a combined `EvalResults` where each variant is named after its model string. Parameters ---------- persona Persona name to evaluate (e.g., `"code_reviewer"`). models List of provider:model strings (e.g., `["anthropic:claude-sonnet-4-6", "github:gpt-4o"]`). queries Queries to evaluate. Falls back to persona `test_queries`. dimensions Scoring dimensions. Defaults to relevance, safety, instruction_adherence. judge Judge model string or ChatBot. default_guards Whether to apply persona default guards (passed through to `persona_pack()`). scorecard_path If provided, writes the scorecard JSON to this path after evaluation. Returns ------- EvalResults Combined results with one variant per model. Raises ------ ValueError If `models` is empty. Examples -------- Compare a persona across two providers: ```python import talk_box as tb results = tb.eval_suite( "code_reviewer", models=["anthropic:claude-sonnet-4-6", "github:gpt-4o"], judge="anthropic:claude-sonnet-4-6", ) results.to_scorecard("scorecards/code_reviewer.json") results.to_great_table() ``` EvalCase(query: 'str', context: 'str' = '', tags: 'tuple[str, ...]' = ()) -> None A single evaluation test case. Parameters ---------- query The user message to send to the bot. context Optional context about what a good response should contain. tags Optional tags for filtering/grouping results. EvalDimension(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Scoring dimensions for evaluation. EvalResults(results: 'list[EvalResult]' = , config: 'dict[str, Any]' = ) -> None Collection of evaluation results with reporting capabilities. Parameters ---------- results List of individual eval results. config Metadata about the evaluation run. summary(self) -> 'dict[str, Any]' Compute summary statistics for the eval run. Returns ------- dict[str, Any] Summary with total queries, variants, dimension means, and overall scores. passed(self, threshold: 'float' = 0.7) -> 'bool' Check if all variants meet the minimum threshold. Parameters ---------- threshold Minimum acceptable average score (0.0 to 1.0). Returns ------- bool True if all variants have an overall score >= threshold. regressions(self, baseline: 'str | None' = None, threshold: 'float' = 0.05) -> 'dict[str, dict[str, float]]' Detect regressions between variants. Compares each variant to the baseline and returns dimensions where the score dropped by more than `threshold`. Parameters ---------- baseline Variant name to use as baseline. Defaults to the first variant. threshold Minimum score drop to flag as a regression. Returns ------- dict[str, dict[str, float]] Mapping of variant name -> dimension -> score delta (negative = regression). scores_by_variant(self) -> 'dict[str, dict[str, float]]' Aggregate mean scores per variant per dimension. Returns ------- dict[str, dict[str, float]] Mapping of variant name -> dimension name -> mean score. to_dataframe(self) -> "'pd.DataFrame'" Export results to a pandas DataFrame. Returns ------- pd.DataFrame DataFrame with one row per (variant, query, dimension) combination. Raises ------ ImportError If pandas is not installed. to_great_table(self) -> "'gt.GT'" Create a Great Tables comparison report. Produces a summary table showing mean scores per variant per dimension, with color-coded cells indicating quality levels. Returns ------- gt.GT A formatted Great Tables object ready for display or export. Raises ------ ImportError If great_tables or pandas are not installed. to_scorecard(self, path: 'str | Path | None' = None) -> 'dict[str, Any]' Export results as a scorecard dictionary (optionally written to JSON). The scorecard is a portable representation of evaluation results suitable for committing to a repository or publishing to a docs site. Parameters ---------- path Optional file path to write the scorecard JSON. Directories are created automatically. Returns ------- dict[str, Any] Scorecard with metadata, per-variant scores, and overall results. EvalResult(variant: 'str', query: 'str', response: 'str', scores: 'list[EvalScore]' = , duration: 'float' = 0.0) -> None Results for a single query evaluated against a single bot variant. Parameters ---------- variant Name of the bot variant. query The query that was sent. response The bot's response. scores List of dimension scores from the judge. duration Time in seconds to generate the response. EvalScore(dimension: 'EvalDimension | str', score: 'float', explanation: 'str' = '') -> None A score on a single dimension for a single response. Parameters ---------- dimension Which dimension was scored. For built-in dimensions this is an ``EvalDimension`` enum; for custom metrics it is a plain string. score Numeric score from 0.0 to 1.0. explanation Judge's or metric's explanation for the score. scorecard_table(source: 'str | Path | dict[str, Any]') -> "'gt.GT'" Render a scorecard as a polished Great Table. Takes the output of ``EvalResults.to_scorecard()`` (a dict or JSON file) and produces a publication-ready table with color-coded score cells. Parameters ---------- source Path to a scorecard JSON file, or a scorecard dict returned by ``EvalResults.to_scorecard()``. Returns ------- gt.GT A formatted Great Table ready for display, ``.save("file.html")``, or embedding in a Quarto document. Raises ------ ImportError If great_tables or pandas is not installed. Examples -------- From a file: ```python import talk_box as tb table = tb.scorecard_table("scorecards/code_reviewer/2025-05-07.json") table # renders in notebook / Quarto ``` From an in-memory scorecard: ```python results = tb.eval_suite("code_reviewer", models=[...], judge=...) table = tb.scorecard_table(results.to_scorecard()) table.save("scorecard.html") ``` sweep_table(source: 'str | Path | dict[str, Any]') -> "'gt.GT'" Render an eval sweep summary as a polished Great Table. Takes the combined sweep output from ``run_eval_sweep.py`` and produces a persona × model matrix with color-coded overall scores and pass/fail status. Parameters ---------- source Path to a sweep summary JSON file, or a sweep dict. Returns ------- gt.GT A formatted Great Table ready for display, ``.save("file.html")``, or embedding in a Quarto document. Raises ------ ImportError If great_tables or pandas is not installed. Examples -------- ```python import talk_box as tb table = tb.sweep_table("scorecards/_sweeps/2025-05-07T12-00-00.json") table.save("sweep_report.html") ``` ## Model Profiles Model capability registry for routing, eval, and prompt optimization. ModelProfile(provider: 'str', model: 'str', display_name: 'str' = '', context_window: 'int | None' = None, max_output_tokens: 'int | None' = None, supports_tools: 'bool | None' = None, supports_vision: 'bool | None' = None, supports_structured_output: 'bool | None' = None, supports_streaming: 'bool | None' = None, cost_tier: 'CostTier | None' = None, knowledge_cutoff: 'str | None' = None, notes: 'str' = '') -> None Capability profile for a specific LLM model. Parameters ---------- provider Provider name (e.g., `"anthropic"`, `"openai"`, `"ollama"`). model Model identifier (e.g., `"claude-sonnet-4-6"`, `"gpt-4o"`). display_name Human-readable name for display in tables and reports. context_window Maximum context window size in tokens. max_output_tokens Maximum output tokens the model can generate, if known. supports_tools Whether the model supports tool/function calling. supports_vision Whether the model can process image inputs. supports_structured_output Whether the model supports structured (JSON schema) output. supports_streaming Whether the model supports streaming responses. cost_tier Relative cost tier for the model. knowledge_cutoff Knowledge cutoff date string (e.g., "2025-04"), if known. notes Any additional notes about the model. ModelProfile.key Canonical ``provider:model`` key. ModelProfile.name Display name, falling back to model identifier. supports(self, capability: 'str') -> 'bool | None' Check whether a capability is supported. Parameters ---------- capability One of `"tools"``, `"vision"``, `"structured_output"``, `"streaming"`. Returns ------- bool | None `True`/`False` if known, `None` if unknown. Raises ------ ValueError If the capability name is not recognised. CostTier(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Relative cost tier for a model. get_model_profile(model_key: 'str') -> 'ModelProfile | None' Look up a model's capability profile. Parameters ---------- model_key Either a `"provider:model"` string (e.g., `"anthropic:claude-sonnet-4-6"`) or a bare model name (e.g., `"gpt-4o"`). Bare names are searched across all providers; the first match is returned. Returns ------- ModelProfile | None The profile if found, otherwise `None`. Examples -------- ```python import talk_box as tb profile = tb.get_model_profile("anthropic:claude-sonnet-4-6") profile.context_window # 200_000 profile.supports_tools # True profile.cost_tier # CostTier.HIGH ``` list_models(*, provider: 'str | None' = None, supports_tools: 'bool | None' = None, supports_vision: 'bool | None' = None, cost_tier: 'CostTier | None' = None) -> 'list[ModelProfile]' List known model profiles, optionally filtered. Parameters ---------- provider Filter to a specific provider (e.g., `"anthropic"`). supports_tools Filter to models that support (or don't support) tool calling. supports_vision Filter to models that support (or don't support) vision. cost_tier Filter to a specific cost tier. Returns ------- list[ModelProfile] Matching profiles, sorted by provider then model name. Examples -------- ```python import talk_box as tb # All Anthropic models tb.list_models(provider="anthropic") # Free models with tool support tb.list_models(supports_tools=True, cost_tier=tb.CostTier.FREE) # Models that support vision tb.list_models(supports_vision=True) ``` register_model(profile: 'ModelProfile') -> 'None' Register a custom model profile. Use this to add profiles for models not included in the built-in registry (e.g., fine-tuned models or new releases). Parameters ---------- profile The model profile to register. Examples -------- ```python import talk_box as tb tb.register_model(tb.ModelProfile( provider="openai", model="ft:gpt-4o:my-org:custom:id", display_name="My Fine-tuned GPT-4o", context_window=128_000, supports_tools=True, supports_vision=True, supports_structured_output=True, supports_streaming=True, cost_tier=tb.CostTier.HIGH, )) ``` model_profiles_table() -> "'gt.GT'" Render all known model profiles as a Great Table. Returns ------- gt.GT A formatted table with one row per model, showing capabilities, context window, and cost tier. Raises ------ ImportError If great_tables or pandas is not installed. Examples -------- ```python import talk_box as tb tb.model_profiles_table() # renders in notebook / Quarto ``` ## Ollama Detection Auto-detect local Ollama instances and register available models. OllamaStatus(available: 'bool', url: 'str', version: 'str' = '', models: 'list[str] | None' = None, error: 'str' = '') -> None Status of the local Ollama instance. Parameters ---------- available Whether Ollama is reachable. url The base URL that was checked. version Ollama server version string, if available. models List of model names currently pulled/available. error Error message if Ollama is not reachable. detect_ollama(url: 'str | None' = None, *, timeout: 'float' = 2.0) -> 'OllamaStatus' Detect whether a local Ollama instance is running. Pings the Ollama HTTP API and returns connection status, server version, and the list of available models. Parameters ---------- url Base URL for the Ollama API. Defaults to `http://localhost:11434`. Can also be set via the `OLLAMA_HOST` environment variable. timeout Connection timeout in seconds. Returns ------- OllamaStatus Status object with availability, version, and model list. Examples -------- ```python import talk_box as tb status = tb.detect_ollama() if status.available: print(f"Ollama {status.version} running with {len(status.models)} models") for model in status.models: print(f" - {model}") else: print(f"Ollama not available: {status.error}") ``` list_ollama_models(url: 'str | None' = None, *, timeout: 'float' = 5.0) -> 'list[ModelProfile]' Query Ollama for available models and return their profiles. Connects to the Ollama API, retrieves the list of pulled models with their metadata, and returns `ModelProfile` instances for each. Parameters ---------- url Base URL for the Ollama API. Defaults to `http://localhost:11434` or the `OLLAMA_HOST` environment variable. timeout Connection timeout in seconds. Returns ------- list[ModelProfile] A profile for each model available in Ollama. Returns an empty list if Ollama is not reachable. Examples -------- ```python import talk_box as tb models = tb.list_ollama_models() for m in models: print(f"{m.model}: {m.context_window:,} tokens, tools={m.supports_tools}") ``` sync_ollama_models(url: 'str | None' = None, *, timeout: 'float' = 5.0) -> 'list[ModelProfile]' Detect Ollama models and register them in the profile registry. Combines `list_ollama_models()` with `register_model()`, and discovered models are added to the global registry so they appear in `list_models(provider="ollama")`, `get_model_profile()`, and `model_profiles_table()`. Parameters ---------- url Base URL for the Ollama API. timeout Connection timeout in seconds. Returns ------- list[ModelProfile] The profiles that were registered. Empty if Ollama is unreachable. Examples -------- ```python import talk_box as tb # Sync local models into the registry new_models = tb.sync_ollama_models() print(f"Registered {len(new_models)} Ollama models") # Now they're queryable tb.list_models(provider="ollama") ``` ## Context Window Management Token-aware fitting of prompts and messages within model context limits. ContextWindow(*, max_tokens: 'int | None' = None, model: 'str | ModelProfile | None' = None, reserve_output: 'int' = 1024, strategy: 'str | FitStrategy' = , token_counter: 'Callable[[str], int] | None' = None) -> 'None' Manages fitting content into a model's token budget. Combines token estimation with truncation strategies to ensure prompts and conversation messages stay within a model's context window. Parameters ---------- max_tokens Explicit token budget. If provided, overrides any model profile lookup. model A model key (e.g., `"ollama:llama3.2:latest"`) or a `~talk_box.models.ModelProfile` instance. The profile's `context_window` is used as the budget. reserve_output Tokens to reserve for the model's response. Subtracted from the budget before fitting input content. Defaults to 1024. strategy The default strategy for fitting content. Can be overridden per call. token_counter Optional custom token counting function. Defaults to `estimate_tokens`. Examples -------- ```python import talk_box as tb # From a model profile ctx = tb.ContextWindow(model="ollama:llama3.2:latest") # With explicit budget ctx = tb.ContextWindow(max_tokens=8192) # With custom settings ctx = tb.ContextWindow( max_tokens=32_768, reserve_output=4096, strategy="truncate_middle", ) ``` fit_messages(self, messages: 'list[dict[str, str] | Message]', *, system_prompt: 'str' = '', strategy: 'str | FitStrategy | None' = None) -> 'FitResult' Fit a list of conversation messages into the token budget. The system prompt is always preserved. Messages are dropped according to the selected strategy until they fit within the remaining budget. Parameters ---------- messages List of message dicts (with `"role"` and `"content"` keys) or `~talk_box.conversation.Message` objects. system_prompt The system prompt text (always preserved in full). strategy Override the default strategy for this call. Returns ------- FitResult The fitted messages plus metadata about what was dropped. Examples -------- ```python import talk_box as tb ctx = tb.ContextWindow(max_tokens=4096, reserve_output=512) messages = [ {"role": "user", "content": "Hello!"}, {"role": "assistant", "content": "Hi there! How can I help?"}, {"role": "user", "content": "Tell me about Python."}, ] result = ctx.fit_messages(messages, system_prompt="You are helpful.") print(f"Using {result.tokens_used}/{result.token_budget} tokens") print(f"Dropped {result.messages_dropped} messages") ``` fit_prompt(self, builder: 'PromptBuilder') -> 'PromptFitResult' Fit a PromptBuilder's output into the token budget. If the full prompt fits, returns it unchanged. Otherwise, drops lowest-priority sections until it fits. Parameters ---------- builder A `~talk_box.prompt_builder.PromptBuilder` instance. Returns ------- PromptFitResult The fitted prompt text and metadata. Examples -------- ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("analyst", "data science") .task_context("Analyze sales data") .constraint("Be concise") .example("Q: Revenue?", "A: $1.2M") ) ctx = tb.ContextWindow(max_tokens=2048) result = ctx.fit_prompt(builder) print(f"Prompt uses {result.tokens_used} tokens") ``` count_tokens(self, text: 'str') -> 'int' Count tokens in text using the configured counter. Parameters ---------- text The text to count tokens for. Returns ------- int Token count. fits(self, text: 'str') -> 'bool' Check whether text fits within the input budget. Parameters ---------- text Text to check. Returns ------- bool True if token count is within budget. overflow(self, text: 'str') -> 'int' Calculate how many tokens over budget the text is. Parameters ---------- text Text to check. Returns ------- int Number of tokens over budget (0 if within budget). FitResult(messages: 'list[dict[str, str]]', system_prompt: 'str', tokens_used: 'int', token_budget: 'int', messages_dropped: 'int' = 0, strategy_used: 'FitStrategy' = ) -> None Result of fitting content into a context window budget. Parameters ---------- messages The messages that fit within the budget. system_prompt The system prompt (possibly truncated). tokens_used Estimated total tokens consumed. token_budget The total token budget that was targeted. messages_dropped Number of messages that were dropped to fit. strategy_used The strategy that was applied. PromptFitResult(text: 'str', tokens_used: 'int', token_budget: 'int', sections_dropped: 'list[str]' = ) -> None Result of fitting a PromptBuilder output into a token budget. Parameters ---------- text The fitted prompt text. tokens_used Estimated tokens in the fitted text. token_budget The token budget that was targeted. sections_dropped Names/descriptions of sections that were dropped to fit. FitStrategy(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Strategy for fitting content into a token budget. Attributes ---------- TRUNCATE_OLDEST Drop the oldest messages first, preserving the most recent context. TRUNCATE_MIDDLE Keep the first and last messages, dropping from the middle. Preserves the opening context and the most recent exchanges. TRIM_SECTIONS For prompts: drop lowest-priority PromptBuilder sections first. estimate_tokens(text: 'str') -> 'int' Estimate the token count for a string using a character-based heuristic. Uses the approximation of 1 token ≈ 4 characters for English text, which aligns with typical BPE tokenizers (GPT, Claude, Llama). For non-English or code-heavy text, this may undercount slightly. Parameters ---------- text The text to estimate tokens for. Returns ------- int Estimated token count (always at least 1 for non-empty text). Examples -------- ```python import talk_box as tb tokens = tb.estimate_tokens("Hello, world!") print(tokens) # ~4 ``` ## Prompt Optimization Reduce prompt token usage without losing semantic meaning. optimize_prompt(prompt: 'str | PromptBuilder', *, level: 'str | OptimizationLevel' = ) -> 'OptimizeResult' Optimize a prompt for reduced token usage. Applies text-level compression techniques that preserve semantic meaning while reducing token count. Useful when targeting models with small context windows (8K–32K). Parameters ---------- prompt A prompt string or a :class:`~talk_box.prompt_builder.PromptBuilder` instance. If a PromptBuilder, its built output is used. level How aggressively to compress. ``"light"`` is formatting-only, ``"moderate"`` (default) condenses structure, ``"aggressive"`` maximizes compression. Returns ------- OptimizeResult The optimized text with before/after token counts. Examples -------- ```python import talk_box as tb builder = ( tb.PromptBuilder() .persona("analyst", "data science") .task_context("Analyze sales data") .constraint("Be concise") .example("Q: Revenue?", "A: $1.2M") ) result = tb.optimize_prompt(builder) print(f"Saved {result.reduction_pct:.0f}% tokens") print(result.text) ``` OptimizationLevel(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) How aggressively to compress prompts. Attributes ---------- LIGHT Remove unnecessary formatting only. Safe for all models. MODERATE Condense whitespace, compact examples, shorten boilerplate. AGGRESSIVE Maximum compression: strip all formatting, merge sections, truncate long content. OptimizeResult(text: 'str', original_tokens: 'int', optimized_tokens: 'int', reduction_pct: 'float', level: 'OptimizationLevel') -> None Result of prompt optimization. Parameters ---------- text The optimized prompt text. original_tokens Estimated tokens before optimization. optimized_tokens Estimated tokens after optimization. reduction_pct Percentage of tokens saved. level The optimization level that was applied. ## Hybrid Routing Route tasks between local and cloud models based on complexity and cost. route(prompt: 'str', *, strategy: 'RoutingStrategy' = , requires: 'list[str] | None' = None, max_cost_tier: 'CostTier | None' = None, prefer_local: 'bool' = False, candidates: 'list[str] | None' = None, min_context_window: 'int | None' = None) -> 'RoutingResult' Route a task to the best available model. This is a convenience function that creates a temporary `Router` instance. For repeated routing, create a `Router` directly to avoid re-filtering the candidate pool each time. Parameters ---------- prompt The task or prompt text to route. strategy Routing strategy to use. requires Required capabilities (e.g., ``["tools", "vision"]``). max_cost_tier Maximum cost tier to consider. prefer_local Whether to prefer local (Ollama) models. candidates Specific model keys to consider. ``None`` uses all registered models. min_context_window Minimum context window size required. Returns ------- RoutingResult The selected model, reason, complexity, and alternatives. Raises ------ ValueError If no candidate models meet the requirements. Examples -------- ```python import talk_box as tb # Simple routing with defaults result = tb.route("Summarize this paragraph") result.model.name # e.g., "GPT-4o Mini" # Prefer local models, cap cost at MEDIUM result = tb.route( "Explain decorators in Python", strategy=tb.RoutingStrategy.LOCAL_FIRST, max_cost_tier=tb.CostTier.MEDIUM, ) # Require specific capabilities result = tb.route( "Analyze this image and describe what you see", requires=["vision"], strategy=tb.RoutingStrategy.QUALITY_OPTIMIZED, ) ``` classify_complexity(prompt: 'str') -> 'TaskComplexity' Estimate the complexity of a task from its prompt text. Uses heuristics based on prompt length, vocabulary, and structural markers to classify the task into one of four complexity levels. Parameters ---------- prompt The prompt text to classify. Returns ------- TaskComplexity The estimated complexity level. Examples -------- ```python import talk_box as tb tb.classify_complexity("What is Python?") # TaskComplexity.SIMPLE tb.classify_complexity("Design a distributed caching system with consistency guarantees") # TaskComplexity.EXPERT ``` Router(*, strategy: 'RoutingStrategy' = , candidates: 'list[str] | None' = None, max_cost_tier: 'CostTier | None' = None, prefer_local: 'bool' = False) -> 'None' Configurable model router for hybrid local/cloud routing. The router maintains a pool of candidate models and selects the best one for a given task based on the configured strategy, required capabilities, and cost constraints. Parameters ---------- strategy Default routing strategy. Can be overridden per-call. candidates List of model keys (e.g., ``"anthropic:claude-sonnet-4-6"``) to consider. If ``None``, uses all models in the registry. max_cost_tier Maximum cost tier to consider. Models above this tier are excluded. prefer_local Whether to give bonus scoring to local (Ollama) models. Examples -------- ```python import talk_box as tb router = tb.Router( strategy=tb.RoutingStrategy.LOCAL_FIRST, max_cost_tier=tb.CostTier.MEDIUM, ) result = router.route("What is a decorator in Python?") result.model.name # e.g., "Llama 3.3 (Ollama)" result.complexity # TaskComplexity.SIMPLE result.reason # "Local model sufficient for simple task" ``` route(self, prompt: 'str', *, strategy: 'RoutingStrategy | None' = None, requires: 'list[str] | None' = None, max_cost_tier: 'CostTier | None' = None, min_context_window: 'int | None' = None) -> 'RoutingResult' Route a task to the best available model. Parameters ---------- prompt The task or prompt text to route. strategy Override the router's default strategy for this call. requires Required capabilities (e.g., ``["tools", "vision"]``). max_cost_tier Override the router's default max cost tier for this call. min_context_window Minimum context window size required. Returns ------- RoutingResult The selected model, reason, complexity, and alternatives. Raises ------ ValueError If no candidate models meet the requirements. Examples -------- ```python import talk_box as tb router = tb.Router() # Route a simple question cheaply result = router.route("Define polymorphism") # Route a complex task requiring tools result = router.route( "Analyze this dataset and generate charts", requires=["tools", "vision"], strategy=tb.RoutingStrategy.QUALITY_OPTIMIZED, ) ``` RoutingStrategy(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Strategy that governs how the router selects models. Attributes ---------- COST_OPTIMIZED Prefer the cheapest model that meets requirements. QUALITY_OPTIMIZED Prefer the most capable model available. LOCAL_FIRST Prefer local models; fall back to cloud only when capabilities are missing. BALANCED Balance cost and quality, preferring mid-tier models. RoutingResult(model: 'ModelProfile', reason: 'str', complexity: 'TaskComplexity', alternatives: 'list[ModelProfile]' = ) -> None Result of routing a task to a model. Parameters ---------- model The selected model profile. reason Human-readable explanation of why this model was chosen. complexity The estimated task complexity. alternatives Other candidate models that also met requirements, ranked by preference. TaskComplexity(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Estimated complexity of a task or prompt. Used by the router to match tasks to appropriately-capable models. ## Consensus Mode Query multiple models, compare outputs, and resolve disagreements. consensus(responses: 'list[ModelResponse]', *, strategy: 'ConsensusStrategy' = , unanimous_threshold: 'float' = 0.7) -> 'ConsensusResult' Determine consensus across multiple model responses. Compares the provided responses and selects a winner based on the chosen strategy. Also detects and reports disagreements. Parameters ---------- responses List of model responses to compare. Must contain at least one response. strategy The consensus strategy to use. unanimous_threshold For the ``UNANIMOUS`` strategy, the minimum pairwise similarity required for consensus to be reached (default 0.7). Returns ------- ConsensusResult The consensus outcome including winner, agreement score, and disagreements. Raises ------ ValueError If ``responses`` is empty. Examples -------- ```python import talk_box as tb responses = [ tb.ModelResponse(model="anthropic:claude-sonnet-4-6", text="Python is a programming language."), tb.ModelResponse(model="openai:gpt-4o", text="Python is a high-level programming language."), tb.ModelResponse(model="google:gemini-2.5-flash", text="Python is an interpreted programming language."), ] result = tb.consensus(responses, strategy=tb.ConsensusStrategy.MAJORITY) result.winner # "Python is a high-level programming language." result.agreement_score # ~0.75 result.consensus_reached # True ``` find_disagreements(responses: 'list[ModelResponse]') -> 'list[Disagreement]' Detect disagreements between model responses. Compares each pair of responses and flags significant differences. Uses word-level similarity to classify severity. Parameters ---------- responses List of model responses to compare. Returns ------- list[Disagreement] Detected disagreements, sorted by severity (major first). Examples -------- ```python import talk_box as tb responses = [ tb.ModelResponse(model="model_a", text="Python was created in 1991."), tb.ModelResponse(model="model_b", text="Python was created in 1989."), ] disagreements = tb.find_disagreements(responses) disagreements[0].severity # "major" ``` ConsensusStrategy(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Strategy for resolving consensus across multiple model responses. Attributes ---------- MAJORITY The response most similar to the majority wins. UNANIMOUS All responses must substantially agree; otherwise consensus fails. MOST_COMMON Select the most frequently occurring response (exact or near-match). WEIGHTED Responses are weighted by model quality/cost tier (higher tier = more weight). ConsensusResult(winner: 'str', winner_model: 'str', agreement_score: 'float', strategy: 'ConsensusStrategy', responses: 'list[ModelResponse]' = , disagreements: 'list[Disagreement]' = , consensus_reached: 'bool' = True) -> None Result of running consensus across multiple model responses. Parameters ---------- winner The winning/selected response text. winner_model The model that produced the winning response. agreement_score Overall agreement score from 0.0 (complete disagreement) to 1.0 (unanimous). strategy The consensus strategy that was used. responses All individual model responses that were compared. disagreements Detected disagreements between responses. consensus_reached Whether consensus was successfully reached (relevant for UNANIMOUS strategy). ModelResponse(model: 'str', text: 'str', latency_ms: 'float | None' = None, token_count: 'int | None' = None, weight: 'float' = 1.0) -> None A single model's response to a prompt. Parameters ---------- model Model identifier (e.g., ``"anthropic:claude-sonnet-4-6"``). text The response text from the model. latency_ms Response latency in milliseconds, if measured. token_count Number of tokens in the response, if known. weight Optional weight for weighted consensus (default 1.0). Disagreement(description: 'str', models: 'tuple[str, ...]', severity: 'str' = 'moderate') -> None A detected disagreement between model responses. Parameters ---------- description Human-readable description of the disagreement. models The models involved in the disagreement. severity Severity level: ``"minor"`` (stylistic), ``"moderate"`` (factual nuance), ``"major"`` (contradictory claims). ## Cascade Consensus Start with one model, fan out to additional models when confidence is low. estimate_confidence(response: 'str') -> 'float' Estimate confidence in a model response based on textual signals. Uses heuristics based on hedging language, assertiveness, response length, and structural indicators to produce a confidence score. Parameters ---------- response The response text to analyze. Returns ------- float Confidence score from 0.0 (very low confidence) to 1.0 (very high confidence). Examples -------- ```python import talk_box as tb tb.estimate_confidence("The answer is 42.") # ~0.75 tb.estimate_confidence("I'm not sure, but maybe it's 42?") # ~0.35 tb.estimate_confidence("I cannot answer that question.") # ~0.15 ``` CascadeResult(winner: 'str', winner_model: 'str', confidence: 'float', fanned_out: 'bool', rounds: 'list[CascadeRound]' = , consensus_strategy: 'ConsensusStrategy | None' = None, agreement_score: 'float | None' = None, initial_model: 'str' = '', initial_confidence: 'float' = 0.0, complexity: 'TaskComplexity' = ) -> None Result of a cascade consensus execution. Parameters ---------- winner The final selected response text. winner_model The model that produced the winning response. confidence Confidence in the final result. fanned_out Whether the cascade fanned out to additional models. rounds Details of each round in the cascade. consensus_strategy The consensus strategy used if fan-out occurred, or ``None``. agreement_score Agreement score from consensus (if fan-out occurred), or ``None``. initial_model The model used in the initial round. initial_confidence The confidence score from the initial round. complexity The estimated task complexity. CascadeRound(round_number: 'int', model: 'str', response: 'str', confidence: 'float') -> None Record of a single round in a cascade execution. Parameters ---------- round_number The round number (1-based). model The model queried in this round. response The response text from the model. confidence Estimated confidence in the response (0.0–1.0). ## Memory Tiers Working, short-term, and long-term memory for conversations. MemoryStore(*, short_term_max_entries: 'int' = 100, short_term_default_ttl: 'float' = 3600.0, long_term_path: 'str | Path' = ':memory:') -> 'None' Unified memory interface across all three tiers. Provides a single API for storing and retrieving memories, with automatic tier selection and cross-tier search. Parameters ---------- short_term_max_entries Maximum entries for the short-term tier (default 100). short_term_default_ttl Default TTL for short-term entries in seconds (default 3600). long_term_path Path to the SQLite database for long-term storage. Use ``":memory:"`` for testing (default). Examples -------- ```python import talk_box as tb store = tb.MemoryStore(long_term_path="my_bot.db") # Store in different tiers store.remember("user_query", "What is Python?", tier=tb.MemoryTier.WORKING) store.remember("session_topic", "Python basics", tier=tb.MemoryTier.SHORT_TERM) store.remember("user_pref", {"theme": "dark"}, tier=tb.MemoryTier.LONG_TERM) # Recall from any tier store.recall("user_query") # Searches working first store.recall("user_pref") # Found in long-term # Search across tiers store.search(tags=["user"]) store.close() ``` remember(self, key: 'str', value: 'Any', *, tier: 'MemoryTier' = , ttl: 'float | None' = None, tags: 'tuple[str, ...]' = (), metadata: 'dict[str, Any] | None' = None) -> 'None' Store a memory in the specified tier. Parameters ---------- key The key to store under. value The value to store. tier Which memory tier to use (default ``WORKING``). ttl Time-to-live in seconds (only used for ``SHORT_TERM``). tags Optional tags for categorization. metadata Optional metadata (only used for ``LONG_TERM``). recall(self, key: 'str', *, tier: 'MemoryTier | None' = None, default: 'Any' = None) -> 'Any' Retrieve a memory, searching tiers if no specific tier is given. When ``tier`` is ``None``, searches working → short-term → long-term and returns the first match found. Parameters ---------- key The key to look up. tier Specific tier to search. ``None`` searches all tiers. default Value to return if not found in any tier. Returns ------- Any The stored value, or ``default`` if not found. forget(self, key: 'str', *, tier: 'MemoryTier | None' = None) -> 'bool' Remove a memory from the specified tier, or from all tiers. Parameters ---------- key The key to remove. tier Specific tier to remove from. ``None`` removes from all tiers. Returns ------- bool ``True`` if the key was found and removed from at least one tier. search(self, *, tags: 'list[str] | None' = None, tier: 'MemoryTier | None' = None, prefix: 'str | None' = None) -> 'list[MemoryEntry]' Search memories across tiers. Parameters ---------- tags Filter to entries with all of these tags. tier Specific tier to search. ``None`` searches all tiers. prefix Key prefix filter (only supported for long-term tier). Returns ------- list[MemoryEntry] Matching entries from the specified tier(s). WorkingMemory() -> 'None' In-conversation key-value memory, lost when the conversation ends. This is the fastest tier — a simple dict-backed store for transient data needed during a single conversation turn or session. Examples -------- ```python import talk_box as tb wm = tb.WorkingMemory() wm.set("user_name", "Alice") wm.get("user_name") # "Alice" wm.keys() # ["user_name"] wm.clear() ``` ShortTermMemory(*, max_entries: 'int' = 100, default_ttl: 'float' = 3600.0) -> 'None' Recent session memory with TTL and max-entry eviction. Entries expire after their TTL elapses. When the store exceeds ``max_entries``, the oldest entries are evicted first. Parameters ---------- max_entries Maximum number of entries to retain (default 100). default_ttl Default time-to-live in seconds for new entries (default 3600 = 1 hour). Examples -------- ```python import talk_box as tb stm = tb.ShortTermMemory(max_entries=50, default_ttl=1800) stm.set("last_topic", "Python decorators") stm.get("last_topic") # "Python decorators" ``` LongTermMemory(path: 'str | Path' = ':memory:') -> 'None' Persistent memory backed by SQLite. Entries persist across sessions and are stored in a SQLite database file. Supports search by key prefix, tags, and full listing. Parameters ---------- path Path to the SQLite database file. Use ``":memory:"`` for an in-memory database (useful for testing). Examples -------- ```python import talk_box as tb ltm = tb.LongTermMemory("my_memory.db") ltm.set("preference", {"theme": "dark", "language": "en"}) ltm.get("preference") # {"theme": "dark", "language": "en"} ltm.search(tags=["user"]) ltm.close() ``` MemoryEntry(key: 'str', value: 'Any', tier: 'MemoryTier', timestamp: 'float' = 0.0, ttl: 'float | None' = None, tags: 'tuple[str, ...]' = (), metadata: 'dict[str, Any]' = ) -> None A single memory entry across any tier. Parameters ---------- key Unique identifier for this memory within its tier. value The stored value (any JSON-serializable object). tier Which memory tier this entry belongs to. timestamp Unix timestamp when the entry was created or last updated. ttl Time-to-live in seconds. ``None`` means no expiration. tags Tags for categorization and search. metadata Additional metadata about this entry. MemoryTier(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Which memory tier an entry belongs to. Attributes ---------- WORKING In-conversation memory, lost when the conversation ends. SHORT_TERM Recent session memory with TTL and max entries. LONG_TERM Persistent memory backed by SQLite. ## WorkingMemory Methods Methods for the WorkingMemory class set(self, key: 'str', value: 'Any', *, tags: 'tuple[str, ...]' = ()) -> 'None' Store a value in working memory. Parameters ---------- key The key to store under. value The value to store. tags Optional tags for categorization. get(self, key: 'str', default: 'Any' = None) -> 'Any' Retrieve a value from working memory. Parameters ---------- key The key to look up. default Value to return if key is not found. Returns ------- Any The stored value, or ``default`` if not found. has(self, key: 'str') -> 'bool' Check if a key exists in working memory. delete(self, key: 'str') -> 'bool' Remove a key from working memory. Returns ------- bool ``True`` if the key existed and was removed, ``False`` otherwise. keys(self) -> 'list[str]' List all keys in working memory. entries(self) -> 'list[MemoryEntry]' List all entries in working memory. search(self, *, tags: 'list[str] | None' = None) -> 'list[MemoryEntry]' Search working memory by tags. Parameters ---------- tags Filter to entries that have all of these tags. Returns ------- list[MemoryEntry] Matching entries. clear(self) -> 'None' Remove all entries from working memory. __len__(self) -> 'int' ## ShortTermMemory Methods Methods for the ShortTermMemory class set(self, key: 'str', value: 'Any', *, ttl: 'float | None' = None, tags: 'tuple[str, ...]' = ()) -> 'None' Store a value in short-term memory. Parameters ---------- key The key to store under. value The value to store. ttl Time-to-live in seconds. Uses ``default_ttl`` if not specified. tags Optional tags for categorization. get(self, key: 'str', default: 'Any' = None) -> 'Any' Retrieve a value from short-term memory. Expired entries are treated as missing and automatically removed. Parameters ---------- key The key to look up. default Value to return if key is not found or expired. Returns ------- Any The stored value, or ``default`` if not found/expired. has(self, key: 'str') -> 'bool' Check if a key exists and is not expired. delete(self, key: 'str') -> 'bool' Remove a key from short-term memory. Returns ------- bool ``True`` if the key existed and was removed. keys(self) -> 'list[str]' List all non-expired keys. entries(self) -> 'list[MemoryEntry]' List all non-expired entries. search(self, *, tags: 'list[str] | None' = None) -> 'list[MemoryEntry]' Search short-term memory by tags. Parameters ---------- tags Filter to entries that have all of these tags. Returns ------- list[MemoryEntry] Matching non-expired entries. clear(self) -> 'None' Remove all entries. __len__(self) -> 'int' ## LongTermMemory Methods Methods for the LongTermMemory class set(self, key: 'str', value: 'Any', *, tags: 'tuple[str, ...]' = (), metadata: 'dict[str, Any] | None' = None) -> 'None' Store a value in long-term memory. Parameters ---------- key The key to store under. value The value to store (must be JSON-serializable). tags Optional tags for categorization. metadata Optional metadata dictionary. get(self, key: 'str', default: 'Any' = None) -> 'Any' Retrieve a value from long-term memory. Parameters ---------- key The key to look up. default Value to return if key is not found. Returns ------- Any The stored value, or ``default`` if not found. has(self, key: 'str') -> 'bool' Check if a key exists in long-term memory. delete(self, key: 'str') -> 'bool' Remove a key from long-term memory. Returns ------- bool ``True`` if the key existed and was removed. keys(self) -> 'list[str]' List all keys in long-term memory. entries(self) -> 'list[MemoryEntry]' List all entries in long-term memory. search(self, *, tags: 'list[str] | None' = None, prefix: 'str | None' = None) -> 'list[MemoryEntry]' Search long-term memory by tags and/or key prefix. Parameters ---------- tags Filter to entries that have all of these tags. prefix Filter to entries whose key starts with this prefix. Returns ------- list[MemoryEntry] Matching entries, sorted by timestamp. clear(self) -> 'None' Remove all entries from long-term memory. close(self) -> 'None' Close the database connection. __len__(self) -> 'int' ## Agent Self-contained AI agent bundling persona, memory, tools, and conversation history. Agent(name: 'str', persona: 'PersonaDefinition', memory: 'MemoryStore' = , chatbot: 'ChatBot' = None, capture: 'ConversationCapture' = , instructions: 'str' = '', metadata: 'dict[str, Any]' = ) -> None A self-contained AI agent bundling persona, memory, and conversation history. An `Agent` wraps a `ChatBot`, a `PersonaDefinition`, a `MemoryStore`, and a `ConversationCapture` into a single entity that can participate in multi-agent workflows. The agent configures its `ChatBot` automatically from the persona (system prompt, temperature, tools, guardrails) and applies retention policies after each response when a `RetentionPolicy` is attached. Parameters ---------- name Unique identifier for this agent (e.g., `"triage_bot"`). persona The persona definition that drives the agent's behavior. memory The agent's memory store. Defaults to an in-memory store. chatbot A pre-configured `ChatBot`. If `None`, one is built from the persona automatically. capture Conversation capture for recording events. Created automatically if not provided. instructions Additional instructions appended to the persona's system prompt. metadata Arbitrary metadata for the agent (e.g., team, version, owner). Examples -------- Create an agent from a built-in persona: ```python import talk_box as tb agent = tb.Agent.from_persona("code_reviewer") agent.name # "code_reviewer" agent.persona.display_name # "Code Reviewer" ``` Create a custom agent with memory and retention: ```python import talk_box as tb policy = tb.RetentionPolicy( remember_tags=["identity", "preference"], forget_tags=["scratch"], ) agent = tb.Agent( name="support_agent", persona=tb.create_persona( "support", persona_role="customer support specialist", retention=policy, ), memory=tb.MemoryStore(long_term_path="support.db"), ) ``` Respond to a user message: ```python conversation = agent.respond("How do I reset my password?") ``` from_persona(persona_name: 'str', *, name: 'str | None' = None, memory: 'MemoryStore | None' = None, instructions: 'str' = '', metadata: 'dict[str, Any] | None' = None) -> 'Agent' Create an agent from a registered persona name. Parameters ---------- persona_name Name of a registered persona (e.g., `"code_reviewer"`). name Agent name. Defaults to the persona name. memory Memory store. Defaults to an in-memory store. instructions Additional instructions for the agent. metadata Arbitrary metadata. Returns ------- Agent A fully configured agent. Raises ------ KeyError If the persona name is not found. Examples -------- ```python import talk_box as tb agent = tb.Agent.from_persona("data_analyst") agent.name # "data_analyst" ``` respond(self, message: 'str', *, conversation: 'Conversation | None' = None) -> 'Conversation' Send a message and get a response from this agent. Uses the agent's configured `ChatBot` to generate a response. If no conversation is provided, continues the agent's internal conversation (or starts a new one). The agent records prompts and responses in its `capture` and applies its retention policy (if the persona defines one) after each response. Parameters ---------- message The user message to respond to. conversation An existing conversation to continue. If `None`, uses the agent's internal conversation state. Returns ------- Conversation The updated conversation with the response appended. Examples -------- ```python import talk_box as tb agent = tb.Agent.from_persona("python_mentor") convo = agent.respond("What are list comprehensions?") convo = agent.respond("Show me an example", conversation=convo) ``` remember(self, key: 'str', value: 'Any', *, tier: 'MemoryTier' = , tags: 'tuple[str, ...]' = ()) -> 'None' Store a value in the agent's memory. Convenience wrapper around `self.memory.remember()`. Parameters ---------- key The key to store under. value The value to store. tier Which memory tier to use (default `WORKING`). tags Optional tags for categorization. recall(self, key: 'str', default: 'Any' = None) -> 'Any' Retrieve a value from the agent's memory. Convenience wrapper around `self.memory.recall()`. Parameters ---------- key The key to look up. default Value to return if the key is not found. Returns ------- Any The stored value, or *default*. Agent.retention The agent's retention policy (from its persona), if any. Agent.conversation The agent's current conversation, if any. reset_conversation(self) -> 'None' Clear the agent's conversation state and start fresh. ## Agent Methods Methods for the Agent class __post_init__(self) -> 'None' from_persona(persona_name: 'str', *, name: 'str | None' = None, memory: 'MemoryStore | None' = None, instructions: 'str' = '', metadata: 'dict[str, Any] | None' = None) -> 'Agent' Create an agent from a registered persona name. Parameters ---------- persona_name Name of a registered persona (e.g., `"code_reviewer"`). name Agent name. Defaults to the persona name. memory Memory store. Defaults to an in-memory store. instructions Additional instructions for the agent. metadata Arbitrary metadata. Returns ------- Agent A fully configured agent. Raises ------ KeyError If the persona name is not found. Examples -------- ```python import talk_box as tb agent = tb.Agent.from_persona("data_analyst") agent.name # "data_analyst" ``` respond(self, message: 'str', *, conversation: 'Conversation | None' = None) -> 'Conversation' Send a message and get a response from this agent. Uses the agent's configured `ChatBot` to generate a response. If no conversation is provided, continues the agent's internal conversation (or starts a new one). The agent records prompts and responses in its `capture` and applies its retention policy (if the persona defines one) after each response. Parameters ---------- message The user message to respond to. conversation An existing conversation to continue. If `None`, uses the agent's internal conversation state. Returns ------- Conversation The updated conversation with the response appended. Examples -------- ```python import talk_box as tb agent = tb.Agent.from_persona("python_mentor") convo = agent.respond("What are list comprehensions?") convo = agent.respond("Show me an example", conversation=convo) ``` remember(self, key: 'str', value: 'Any', *, tier: 'MemoryTier' = , tags: 'tuple[str, ...]' = ()) -> 'None' Store a value in the agent's memory. Convenience wrapper around `self.memory.remember()`. Parameters ---------- key The key to store under. value The value to store. tier Which memory tier to use (default `WORKING`). tags Optional tags for categorization. recall(self, key: 'str', default: 'Any' = None) -> 'Any' Retrieve a value from the agent's memory. Convenience wrapper around `self.memory.recall()`. Parameters ---------- key The key to look up. default Value to return if the key is not found. Returns ------- Any The stored value, or *default*. reset_conversation(self) -> 'None' Clear the agent's conversation state and start fresh. ## Human-in-the-Loop Pause agent workflows for human review, approval, or revision. human_review(content: 'str', *, agent: 'str' = '', context: 'str' = '', state: 'str' = '', metadata: 'dict[str, Any] | None' = None) -> 'HumanReview' Create a human-in-the-loop review request. Parameters ---------- content The content to be reviewed (e.g., an agent's response, a draft, a proposed action). agent Name of the agent that produced the content. context Additional context for the reviewer. state Pathway state name where the review was requested. metadata Arbitrary metadata. Returns ------- HumanReview A pending review request. Examples -------- ```python import talk_box as tb review = tb.human_review( "Refund $500 to customer account", agent="billing_agent", context="Customer requested refund for order #1234", ) review.status # ReviewStatus.PENDING ``` approve(review: 'HumanReview', *, feedback: 'str' = '', decided_by: 'str' = '') -> 'ReviewDecision' Approve a pending review. Parameters ---------- review The review to approve. feedback Optional feedback from the reviewer. decided_by Identifier for the human making the decision. Returns ------- ReviewDecision The approval decision. Raises ------ ValueError If the review has already been resolved. Examples -------- ```python import talk_box as tb review = tb.human_review("Send email to all users", agent="comms_bot") decision = tb.approve(review, feedback="Approved for send", decided_by="alice") review.is_approved # True review.status # ReviewStatus.APPROVED ``` reject(review: 'HumanReview', *, feedback: 'str' = '', decided_by: 'str' = '') -> 'ReviewDecision' Reject a pending review. Parameters ---------- review The review to reject. feedback Feedback explaining the rejection. decided_by Identifier for the human making the decision. Returns ------- ReviewDecision The rejection decision. Raises ------ ValueError If the review has already been resolved. Examples -------- ```python import talk_box as tb review = tb.human_review("Delete all user data", agent="cleanup_bot") decision = tb.reject(review, feedback="Too risky", decided_by="bob") review.is_approved # False review.status # ReviewStatus.REJECTED ``` revise(review: 'HumanReview', revised_content: 'str', *, feedback: 'str' = '', decided_by: 'str' = '') -> 'ReviewDecision' Revise the content and approve the review. Use when the human wants to modify the agent's output before proceeding. Parameters ---------- review The review to revise. revised_content The corrected or modified content to use instead. feedback Feedback explaining the revision. decided_by Identifier for the human making the decision. Returns ------- ReviewDecision The revision decision. Raises ------ ValueError If the review has already been resolved. Examples -------- ```python import talk_box as tb review = tb.human_review("Refund $500", agent="billing_bot") decision = tb.revise(review, "Refund $250", feedback="Partial refund only") review.final_content # "Refund $250" review.is_approved # True (revised counts as approved) ``` HumanReview(content: 'str', agent: 'str' = '', context: 'str' = '', state: 'str' = '', metadata: 'dict[str, Any]' = , created_at: 'float' = ) -> None A request for human review before proceeding. `HumanReview` captures content produced by an agent (or a pathway state) that requires human approval, rejection, or revision before the workflow continues. Parameters ---------- content The content to be reviewed. agent Name of the agent that produced the content. context Additional context for the reviewer (e.g., task description, instructions). state The pathway state name where the review was requested, if applicable. metadata Arbitrary metadata attached to the review. created_at Unix timestamp when the review was created. Examples -------- Create a review, then approve it: ```python import talk_box as tb review = tb.human_review("Deploy to production?", agent="deploy_bot") review.status # ReviewStatus.PENDING review.is_pending # True decision = tb.approve(review, feedback="Looks good") decision.status # ReviewStatus.APPROVED review.is_resolved # True ``` HumanReview.status Current status of this review. HumanReview.decision The human's decision, or ``None`` if still pending. HumanReview.is_pending Whether the review is still awaiting a decision. HumanReview.is_resolved Whether the review has been decided (approved, rejected, or revised). HumanReview.is_approved Whether the review was approved (including revised). HumanReview.final_content The content to use going forward. Returns the revised content if the review was revised, otherwise the original content. ReviewDecision(status: 'ReviewStatus', feedback: 'str' = '', revised_content: 'str | None' = None, decided_at: 'float' = 0.0, decided_by: 'str' = '') -> None A human's decision on a review request. Parameters ---------- status The decision: approved, rejected, or revised. feedback Optional human feedback explaining the decision. revised_content Replacement content when the decision is ``REVISED``. decided_at Unix timestamp when the decision was made. decided_by Identifier for the human who made the decision. ReviewStatus(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Status of a human-in-the-loop review. Attributes ---------- PENDING The review is awaiting a human decision. APPROVED The human approved the content. REJECTED The human rejected the content. REVISED The human revised the content before approving. ReviewQueue() -> 'None' Collects and tracks multiple review requests. A `ReviewQueue` manages a list of `HumanReview` instances, providing filtering by status and bulk operations. Useful for workflows where multiple agent outputs need human approval. Examples -------- ```python import talk_box as tb queue = tb.ReviewQueue() queue.add(tb.human_review("Draft email", agent="writer")) queue.add(tb.human_review("SQL query", agent="analyst")) queue.pending() # 2 reviews tb.approve(queue.pending()[0]) queue.pending() # 1 review queue.resolved() # 1 review ``` ## ReviewQueue Methods Methods for the ReviewQueue class add(self, review: 'HumanReview') -> 'HumanReview' Add a review to the queue. Parameters ---------- review The review to track. Returns ------- HumanReview The same review, for chaining. pending(self) -> 'list[HumanReview]' Return all pending reviews. Returns ------- list[HumanReview] Reviews that have not yet been decided. resolved(self) -> 'list[HumanReview]' Return all resolved reviews. Returns ------- list[HumanReview] Reviews that have been approved, rejected, or revised. by_agent(self, agent: 'str') -> 'list[HumanReview]' Return reviews from a specific agent. Parameters ---------- agent The agent name to filter by. Returns ------- list[HumanReview] All reviews from the specified agent. by_status(self, status: 'ReviewStatus') -> 'list[HumanReview]' Return reviews matching a specific status. Parameters ---------- status The status to filter by. Returns ------- list[HumanReview] All reviews with the given status. __len__(self) -> 'int' ## Skill System Loadable capability packs for agents. SkillDefinition(name: 'str', display_name: 'str', category: 'str', description: 'str', instructions: 'str' = '', constraints: 'list[str]' = , tools: 'list[str]' = , tags: 'list[str]' = , metadata: 'dict[str, Any]' = ) -> None A loadable skill pack that adds capabilities to an agent. A skill bundles instructions, constraints, tools, and context that can be attached to any `Agent` or `ChatBot` to grant it domain-specific capabilities without modifying the agent's persona. Parameters ---------- name Machine-readable identifier (e.g., `"sql_analysis"`). display_name Human-readable name (e.g., `"SQL Analysis"`). category Grouping category (e.g., `"data"`, `"engineering"`, `"writing"`). description One-line description of what this skill enables. instructions Detailed instructions appended to the system prompt when the skill is active. This is the core of the skill — it tells the agent *how* to perform the capability. constraints Constraints the agent must follow when this skill is active. tools Tool names the skill requires or recommends. tags Free-form tags for filtering and discovery. metadata Arbitrary metadata (e.g., version, author). Examples -------- Create a skill programmatically: ```python import talk_box as tb skill = tb.create_skill( "code_review", description="Review code for quality and security issues", instructions="Analyze code for bugs, security issues, and style. " "Prioritize: security > correctness > performance > style.", constraints=["Always explain the 'why' behind suggestions"], tools=["file_reader"], ) skill.name # "code_review" ``` Register and retrieve: ```python tb.register_skill(skill) tb.get_skill("code_review") # same skill tb.list_skills() # ["code_review"] ``` create_skill(name: 'str', *, display_name: 'str | None' = None, category: 'str' = 'custom', description: 'str' = '', instructions: 'str' = '', constraints: 'list[str] | None' = None, tools: 'list[str] | None' = None, tags: 'list[str] | None' = None, metadata: 'dict[str, Any] | None' = None) -> 'SkillDefinition' Create a skill definition programmatically. Parameters ---------- name Machine-readable identifier (e.g., `"summarizer"`). display_name Human-readable name. Defaults to *name* with underscores replaced by spaces and title-cased. category Grouping category. Defaults to `"custom"`. description One-line description of what this skill enables. instructions Detailed instructions for the agent when this skill is active. constraints Constraints the agent must follow. tools Tool names the skill requires. tags Free-form tags for filtering and discovery. metadata Arbitrary metadata. Returns ------- SkillDefinition The new skill definition. Examples -------- ```python import talk_box as tb skill = tb.create_skill( "summarizer", description="Summarize text into key points", instructions="Read the provided text and produce a concise summary. " "Use bullet points for key takeaways.", constraints=["Keep summaries under 200 words"], tags=["writing", "productivity"], ) ``` get_skill(name: 'str') -> 'SkillDefinition' Get a skill definition by name. Parameters ---------- name The skill name (e.g., `"sql_analysis"`). Returns ------- SkillDefinition The full skill definition. Raises ------ KeyError If no skill with that name exists. Examples -------- ```python import talk_box as tb skill = tb.get_skill("sql_analysis") skill.description ``` list_skills() -> 'list[str]' List all available skill names. Returns ------- list[str] Sorted list of skill names (built-in + registered). Examples -------- ```python import talk_box as tb names = tb.list_skills() ``` register_skill(skill: 'SkillDefinition') -> 'None' Register a skill definition in the global registry. Overwrites any existing skill with the same name. Parameters ---------- skill The skill definition to register. Examples -------- ```python import talk_box as tb skill = tb.create_skill("my_skill", description="Custom skill") tb.register_skill(skill) tb.get_skill("my_skill") # works ``` load_skill(path: 'str | Path') -> 'SkillDefinition' Load a skill from an arbitrary YAML file. Parameters ---------- path Path to a skill YAML file. Returns ------- SkillDefinition The parsed skill definition. Raises ------ FileNotFoundError If the file doesn't exist. Examples -------- ```python import talk_box as tb skill = tb.load_skill("my_skills/summarizer.yaml") ``` skill_categories() -> 'dict[str, list[str]]' Get all skills grouped by category. Returns ------- dict[str, list[str]] Mapping of category name to sorted list of skill names. Examples -------- ```python import talk_box as tb cats = tb.skill_categories() # {"data": ["sql_analysis"], "engineering": ["code_review"], ...} ``` ## Structured Outputs Extract typed data from LLM responses using Pydantic models. ExtractResult(data: 'dict[str, Any]', model_name: 'str', duration: 'float') -> None Result of extracting structured data from an LLM response. Parameters ---------- data The extracted data as a dictionary matching the schema. model_name The model class name used for extraction. duration Wall-clock time in seconds the extraction took. Examples -------- ```python import talk_box as tb from pydantic import BaseModel class Sentiment(BaseModel): label: str score: float bot = tb.ChatBot().model("gpt-4o-mini") result = tb.extract(bot, "I love this product!", data_model=Sentiment) result.data # {"label": "positive", "score": 0.95} result.model_name # "Sentiment" result.duration # 1.23 ``` extract(chatbot: 'Any', message: 'str', *, data_model: 'type', agent: 'Any | None' = None) -> 'ExtractResult' Extract structured data from an LLM response. Sends a message to a `ChatBot` or `Agent` and parses the response into a typed dictionary matching a Pydantic model schema. When the ChatBot has mock responses configured, the first mock response is consumed and parsed as JSON. When a real LLM is configured, the chatlas ``extract_data()`` method is used for provider-native structured output support. Parameters ---------- chatbot A `ChatBot` instance (or the ``chatbot`` attribute of an ``Agent``). message The prompt to send. data_model A Pydantic ``BaseModel`` subclass describing the desired output schema. agent An optional ``Agent`` whose ``chatbot`` will be used. If provided, *chatbot* is ignored. Returns ------- ExtractResult The extracted data, model name, and timing. Raises ------ ValueError If the mock response is not valid JSON matching the schema. Examples -------- With mock responses (for testing): ```python import talk_box as tb from pydantic import BaseModel class City(BaseModel): name: str country: str population: int bot = tb.ChatBot() bot.mock_responses(['{"name": "Paris", "country": "France", "population": 2161000}']) result = tb.extract(bot, "Tell me about Paris", data_model=City) result.data # {"name": "Paris", "country": "France", "population": 2161000} ``` With an Agent: ```python agent = tb.Agent.from_persona("data_analyst") agent.chatbot.mock_responses(['{"name": "Tokyo", "country": "Japan", "population": 13960000}']) result = tb.extract(agent.chatbot, "Tell me about Tokyo", data_model=City, agent=agent) ``` schema_to_dict(data_model: 'type') -> 'dict[str, Any]' Convert a Pydantic model class to a JSON Schema dictionary. Useful for inspecting what schema will be sent to the LLM, logging, or building dynamic schemas. Parameters ---------- data_model A Pydantic ``BaseModel`` subclass. Returns ------- dict[str, Any] The JSON Schema representation of the model. Examples -------- ```python from pydantic import BaseModel import talk_box as tb class Weather(BaseModel): city: str temp_f: float condition: str schema = tb.schema_to_dict(Weather) schema["properties"] # {"city": {...}, "temp_f": {...}, "condition": {...}} schema["required"] # ["city", "temp_f", "condition"] ``` ## Persona Traits Composable modifiers that add constraints, expertise, and tools to any persona. TraitDefinition(name: 'str', display_name: 'str' = '', category: 'str' = 'general', description: 'str' = '', constraints: 'list[str]' = , critical_constraints: 'list[str]' = , expertise_extra: 'str' = '', avoid_topics: 'list[str]' = , tools: 'list[str]' = , tags: 'list[str]' = , temperature: 'float | None' = None, task_context_extra: 'str' = '', output_format: 'list[str]' = , final_emphasis: 'str' = '', metadata: 'dict[str, Any]' = ) -> None A composable modifier that can be applied to any persona. Traits act as mixins — they add constraints, expertise, tools, avoid topics, or tags to an existing ``PersonaDefinition`` without replacing its core identity. Multiple traits can be stacked. Parameters ---------- name Machine-readable identifier (e.g., ``"security_focused"``). display_name Human-readable label (e.g., ``"Security-Focused"``). category Grouping category (e.g., ``"tone"``, ``"compliance"``). description One-line summary of what this trait adds. constraints Constraints appended to the persona's ``constraints`` list. critical_constraints Critical constraints appended to the persona's list. expertise_extra Text appended to the persona's ``expertise`` field. avoid_topics Topics appended to the persona's ``avoid_topics`` list. tools Tools appended to the persona's ``tools`` list. tags Tags appended to the persona's ``tags`` list. temperature If set, overrides the persona's temperature. task_context_extra Text appended to the persona's ``task_context``. output_format Output format directives appended to the persona's list. final_emphasis If set, replaces the persona's ``final_emphasis``. metadata Arbitrary metadata for the trait. Examples -------- Create a trait programmatically: ```python import talk_box as tb sec = tb.create_trait( "security_focused", description="Adds security-related constraints.", constraints=["Flag potential security issues"], critical_constraints=["Never suggest insecure patterns"], ) ``` Apply a trait to a persona: ```python persona = tb.get_persona("code_reviewer") secure_reviewer = tb.apply_trait(persona, sec) secure_reviewer.constraints # includes the security constraint ``` apply_trait(persona: 'Any', trait: 'TraitDefinition') -> 'Any' Apply a trait to a persona, returning a new modified persona. The original persona is not mutated. List fields are merged (de-duplicated), string fields are appended, and ``temperature`` is overridden only when the trait specifies one. Parameters ---------- persona A ``PersonaDefinition`` instance. trait The ``TraitDefinition`` to apply. Returns ------- PersonaDefinition A *new* persona with the trait's modifications merged in. Examples -------- ```python import talk_box as tb persona = tb.get_persona("data_analyst") concise = tb.get_trait("concise") modified = tb.apply_trait(persona, concise) ``` create_trait(name: 'str', *, display_name: 'str' = '', category: 'str' = 'custom', description: 'str' = '', constraints: 'list[str] | None' = None, critical_constraints: 'list[str] | None' = None, expertise_extra: 'str' = '', avoid_topics: 'list[str] | None' = None, tools: 'list[str] | None' = None, tags: 'list[str] | None' = None, temperature: 'float | None' = None, task_context_extra: 'str' = '', output_format: 'list[str] | None' = None, final_emphasis: 'str' = '', metadata: 'dict[str, Any] | None' = None) -> 'TraitDefinition' Create a trait definition programmatically. Parameters ---------- name Machine-readable identifier (e.g., ``"security_focused"``). display_name Human-readable label. Defaults to *name* title-cased. category Grouping category. Defaults to ``"custom"``. description One-line description of what this trait adds. constraints Constraints to append to a persona. critical_constraints Critical constraints to append. expertise_extra Text appended to a persona's expertise. avoid_topics Topics to add to a persona's avoid list. tools Tool names to add. tags Tags to add. temperature Temperature override (applied when the trait is applied). task_context_extra Text appended to a persona's task context. output_format Output format directives to append. final_emphasis Replaces a persona's final emphasis when the trait is applied. metadata Arbitrary metadata. Returns ------- TraitDefinition A new trait definition. Examples -------- ```python import talk_box as tb friendly = tb.create_trait( "junior_friendly", description="Adjusts output for beginners.", constraints=["Explain jargon when first used"], ) ``` get_trait(name: 'str') -> 'TraitDefinition' Get a registered trait by name. Parameters ---------- name The trait name (e.g., ``"concise"``). Returns ------- TraitDefinition The trait definition. Raises ------ KeyError If no trait with that name exists. Examples -------- ```python import talk_box as tb concise = tb.get_trait("concise") concise.description ``` list_traits() -> 'list[str]' List all available trait names. Returns ------- list[str] Sorted list of trait names. Examples -------- ```python import talk_box as tb names = tb.list_traits() "concise" in names # True ``` register_trait(trait: 'TraitDefinition') -> 'None' Register a trait so it can be retrieved with ``get_trait()``. Parameters ---------- trait The trait definition to register. Raises ------ ValueError If a trait with the same name is already registered. Examples -------- ```python import talk_box as tb t = tb.create_trait("my_trait", description="Custom trait.") tb.register_trait(t) tb.get_trait("my_trait") ``` load_trait(path: 'str | Path') -> 'TraitDefinition' Load a trait from an arbitrary YAML file path. Parameters ---------- path Path to a trait YAML file. Returns ------- TraitDefinition The parsed trait definition. Raises ------ FileNotFoundError If the file doesn't exist. Examples -------- ```python import talk_box as tb t = tb.load_trait("my_traits/strict_security.yaml") ``` trait_categories() -> 'dict[str, list[str]]' Get all traits grouped by category. Returns ------- dict[str, list[str]] Mapping of category to sorted list of trait names. Examples -------- ```python import talk_box as tb cats = tb.trait_categories() cats["tone"] # ["concise", "formal", "verbose"] ``` ## MCP Bridge Bidirectional bridge between Talk Box tools and the Model Context Protocol. MCPToolInfo(name: 'str', description: 'str', input_schema: 'dict[str, Any]', server_url: 'str' = '') -> None Description of an MCP tool discovered from a remote server. Parameters ---------- name The tool name as advertised by the MCP server. description Human-readable description of what the tool does. input_schema JSON Schema dict describing the tool's parameters. server_url The URL or transport identifier of the MCP server. Examples -------- ```python import talk_box as tb info = tb.MCPToolInfo( name="search", description="Search the web", input_schema={"type": "object", "properties": {"query": {"type": "string"}}}, server_url="http://localhost:8000/mcp", ) info.name # "search" ``` MCPBridgeServer(name: 'str', tools: 'list[Any]' = , instructions: 'str' = '') -> None An MCP server that exposes Talk Box tools over the MCP protocol. Wraps a collection of ``TalkBoxTool`` instances and serves them via MCP's ``FastMCP`` server. Supports stdio, SSE, and streamable-HTTP transports. Parameters ---------- name Server name shown to MCP clients. tools List of ``TalkBoxTool`` instances to expose. instructions Optional instructions string for the MCP server. Examples -------- Create a server from a tool registry: ```python import talk_box as tb from talk_box.tools import get_global_registry registry = get_global_registry() server = tb.MCPBridgeServer( name="talk-box-tools", tools=registry.get_all_tools(), ) server.tool_names() # ["text_stats", "convert_case", ...] ``` tool_names(self) -> 'list[str]' Return the names of all tools registered with this server. Returns ------- list[str] Sorted list of tool names. build(self) -> 'Any' Build and return a ``FastMCP`` server instance. Each Talk Box tool is registered as an MCP tool. The tool's parameters (excluding the ``context`` parameter) are preserved so MCP clients see the correct input schema. Returns ------- FastMCP A configured ``FastMCP`` server ready to be started with ``run()``. Examples -------- ```python server = tb.MCPBridgeServer(name="my-tools", tools=[my_tool]) mcp_server = server.build() # mcp_server.run() # starts the server ``` run(self, transport: 'str' = 'stdio') -> 'None' Build the server (if needed) and run it. Parameters ---------- transport Transport mode: ``"stdio"``, ``"sse"``, or ``"streamable-http"``. tools_to_mcp_server(tools: 'list[Any]', *, name: 'str' = 'talk-box', instructions: 'str' = '') -> 'MCPBridgeServer' Create an ``MCPBridgeServer`` from a list of Talk Box tools. This is a convenience factory that builds and returns the server in one call. Parameters ---------- tools Talk Box tool instances (``TalkBoxTool``). name Server name. instructions Optional server instructions. Returns ------- MCPBridgeServer A server ready to ``build()`` and ``run()``. Examples -------- ```python import talk_box as tb from talk_box.tools import get_global_registry server = tb.tools_to_mcp_server( get_global_registry().get_all_tools(), name="my-tools", ) mcp = server.build() ``` mcp_tool_to_talk_box(info: 'MCPToolInfo', *, call_fn: 'Callable[..., Any] | None' = None) -> 'Any' Convert an ``MCPToolInfo`` into a ``TalkBoxTool``. This wraps a remote MCP tool so it can be used inside Talk Box conversations just like a native tool. Parameters ---------- info The MCP tool descriptor (from ``list_mcp_tools``). call_fn An optional callable ``(name, arguments) -> result`` used to invoke the remote tool. When omitted a stub that returns the arguments as a JSON string is created (useful for testing). Returns ------- TalkBoxTool A Talk Box tool that delegates to the MCP server. Examples -------- ```python import talk_box as tb info = tb.MCPToolInfo( name="lookup", description="Look up a term", input_schema={ "type": "object", "properties": {"term": {"type": "string"}}, "required": ["term"], }, ) tool = tb.mcp_tool_to_talk_box(info) tool.name # "lookup" ``` list_mcp_tools(tools_data: 'list[dict[str, Any]]', *, server_url: 'str' = '') -> 'list[MCPToolInfo]' Convert raw MCP tool dicts into ``MCPToolInfo`` objects. This is a synchronous helper for when you already have the tool list (e.g. from a cached ``list_tools()`` response). For live discovery, use ``discover_mcp_tools()``. Parameters ---------- tools_data A list of dicts, each with ``name``, ``description``, and ``inputSchema`` keys (matching ``mcp.types.Tool``). server_url Optional server URL to attach to each tool info. Returns ------- list[MCPToolInfo] Parsed tool descriptors. Examples -------- ```python import talk_box as tb raw = [ { "name": "greet", "description": "Say hello", "inputSchema": {"type": "object", "properties": {"name": {"type": "string"}}}, } ] tools = tb.list_mcp_tools(raw) tools[0].name # "greet" ``` discover_mcp_tools(session: 'Any', *, server_url: 'str' = '') -> 'list[MCPToolInfo]' Discover tools from a live MCP client session. Calls ``session.list_tools()`` and converts the results into ``MCPToolInfo`` objects. Parameters ---------- session An ``mcp.client.session.ClientSession`` instance. server_url Optional URL to attach to each tool info. Returns ------- list[MCPToolInfo] Discovered tool descriptors. ## Knowledge Graph SQLite-backed knowledge graph with nodes, edges, traversal, search, and embedding support. KnowledgeGraph(path: 'str | Path' = ':memory:') -> 'None' SQLite-backed knowledge graph with nodes, edges, and optional embeddings. Stores documents, entities, and topics as nodes connected by typed, weighted edges. Supports text search, neighbor traversal, and optional vector embeddings for similarity search. Parameters ---------- path Path to the SQLite database file. Use ``":memory:"`` for an in-memory graph (useful for testing). Examples -------- Create a graph and add nodes: ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") kg.add_node(tb.Node( id="doc-1", node_type=tb.NodeType.DOCUMENT, name="README.md", content="# Talk Box\nAI assistant framework.", )) kg.add_node(tb.Node( id="entity-tb", node_type=tb.NodeType.ENTITY, name="Talk Box", )) kg.add_edge(tb.Edge( source="doc-1", target="entity-tb", relation="mentions", )) neighbors = kg.neighbors("doc-1") neighbors[0].name # "Talk Box" ``` Search nodes by text: ```python results = kg.search("Talk Box") results[0].name # "Talk Box" ``` add_node(self, node: 'Node') -> 'None' Add a node to the graph, or update it if the ID already exists. Parameters ---------- node The node to add or update. Examples -------- ```python kg.add_node(tb.Node( id="topic-ml", node_type=tb.NodeType.TOPIC, name="Machine Learning", )) ``` get_node(self, node_id: 'str') -> 'Node | None' Get a node by ID. Parameters ---------- node_id The node identifier. Returns ------- Node | None The node, or ``None`` if not found. delete_node(self, node_id: 'str') -> 'bool' Delete a node and all its edges. Parameters ---------- node_id The node to remove. Returns ------- bool ``True`` if the node existed and was deleted. list_nodes(self, *, node_type: 'NodeType | None' = None, limit: 'int' = 100) -> 'list[Node]' List nodes, optionally filtered by type. Parameters ---------- node_type Filter to a specific node type. limit Maximum number of nodes to return. Returns ------- list[Node] Matching nodes ordered by name. node_count(self, *, node_type: 'NodeType | None' = None) -> 'int' Count nodes in the graph. Parameters ---------- node_type If provided, count only nodes of this type. Returns ------- int Number of matching nodes. add_edge(self, edge: 'Edge') -> 'None' Add an edge to the graph, or update it if the key already exists. Parameters ---------- edge The edge to add or update. The (source, target, relation) triple is the primary key. Raises ------ KeyError If source or target node does not exist. get_edges(self, node_id: 'str', *, direction: 'str' = 'both', relation: 'str | None' = None) -> 'list[Edge]' Get edges connected to a node. Parameters ---------- node_id The node to query edges for. direction ``"outgoing"``, ``"incoming"``, or ``"both"`` (default). relation Optional filter by relation type. Returns ------- list[Edge] Matching edges. delete_edge(self, source: 'str', target: 'str', relation: 'str') -> 'bool' Delete a specific edge. Parameters ---------- source Source node ID. target Target node ID. relation The relation label. Returns ------- bool ``True`` if the edge existed and was deleted. edge_count(self) -> 'int' Count edges in the graph. Returns ------- int Total number of edges. neighbors(self, node_id: 'str', *, relation: 'str | None' = None, direction: 'str' = 'outgoing') -> 'list[Node]' Get neighboring nodes connected by edges. Parameters ---------- node_id The starting node. relation Optional filter by relation type. direction ``"outgoing"`` (default), ``"incoming"``, or ``"both"``. Returns ------- list[Node] Connected nodes. search(self, query: 'str', *, node_type: 'NodeType | None' = None, limit: 'int' = 20) -> 'list[Node]' Search nodes by name or content (case-insensitive substring match). Parameters ---------- query Text to search for in node names and content. node_type Optional filter by node type. limit Maximum results to return. Returns ------- list[Node] Matching nodes, name matches ranked first. Examples -------- ```python results = kg.search("python", node_type=tb.NodeType.ENTITY) ``` stats(self) -> 'dict[str, Any]' Get summary statistics about the graph. Returns ------- dict[str, Any] Counts of nodes (total and per type) and edges. Examples -------- ```python kg.stats() # {"nodes": 42, "edges": 87, "documents": 10, "entities": 25, "topics": 7} ``` health(self) -> 'dict[str, Any]' Get health metrics for the graph. Reports orphan nodes (no edges), isolated clusters, and embedding coverage. Returns ------- dict[str, Any] Health metrics including orphan count and embedding coverage. Examples -------- ```python report = kg.health() report["orphan_nodes"] # 3 report["embedding_coverage"] # 0.85 ``` pending_questions(self, *, refresh: 'bool' = True, sort_by: 'str' = 'confusion_impact', limit: 'int | None' = None) -> 'list[Any]' Get pending enrichment questions for this knowledge graph. Detects ambiguities (duplicate names, factual conflicts, weak relationships) and returns structured questions sorted by confusion impact. Parameters ---------- refresh If ``True`` (default), run built-in detectors to find new questions before returning. sort_by Sort field: ``"confusion_impact"`` (default, descending) or ``"created_at"`` (ascending, oldest first). limit Maximum questions to return. Defaults to the queue's ``max_per_session`` (7). Returns ------- list[EnrichmentQuestion] Pending questions sorted by priority. Examples -------- ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") # ... add nodes and edges ... questions = kg.pending_questions() for q in questions: print(f"[{q.confusion_impact:.2f}] {q.text}") ``` Skip detection and return only existing questions: ```python questions = kg.pending_questions(refresh=False) ``` answer_question(self, question_id: 'str', *, choice: 'int | None' = None, freeform: 'str | None' = None) -> 'Any | None' Answer a pending enrichment question. At least one of ``choice`` or ``freeform`` must be provided. Parameters ---------- question_id ID of the question to answer. choice Index of the selected option. freeform Freeform text answer. Returns ------- EnrichmentQuestion | None The updated question, or ``None`` if not found or not pending. Raises ------ ValueError If neither ``choice`` nor ``freeform`` is provided, or ``choice`` is out of range. Examples -------- ```python questions = kg.pending_questions() kg.answer_question(questions[0].id, choice=0) kg.answer_question(questions[1].id, freeform="It's the API migration") ``` dismiss_question(self, question_id: 'str') -> 'Any | None' Dismiss a pending enrichment question without answering. Parameters ---------- question_id ID of the question to dismiss. Returns ------- EnrichmentQuestion | None The dismissed question, or ``None`` if not found. Examples -------- ```python kg.dismiss_question("eq-a1b2c3d4") ``` question_stats(self) -> 'dict[str, int]' Get summary statistics for the enrichment question queue. Returns ------- dict[str, int] Counts by status (total, pending, answered, dismissed, expired). Examples -------- ```python kg.question_stats() # {"total": 5, "pending": 3, "answered": 1, ...} ``` clear(self) -> 'None' Delete all nodes and edges from the graph. close(self) -> 'None' Close the database connection. Node(id: 'str', node_type: 'NodeType', name: 'str', content: 'str' = '', metadata: 'dict[str, Any]' = , embedding: 'list[float] | None' = None, created_at: 'float' = 0.0, updated_at: 'float' = 0.0) -> None A node in the knowledge graph. Parameters ---------- id Unique identifier for the node. node_type The type of node (document, entity, or topic). name Human-readable name or title. content Full text content (for documents) or description. metadata Arbitrary key-value metadata. embedding Optional vector embedding as a list of floats. created_at Unix timestamp of creation. updated_at Unix timestamp of last update. Examples -------- ```python import talk_box as tb node = tb.Node( id="doc-001", node_type=tb.NodeType.DOCUMENT, name="README.md", content="# My Project...", ) node.name # "README.md" ``` Edge(source: 'str', target: 'str', relation: 'str', weight: 'float' = 1.0, metadata: 'dict[str, Any]' = ) -> None A directed relationship between two nodes. Parameters ---------- source ID of the source node. target ID of the target node. relation Label describing the relationship (e.g., ``"mentions"``, ``"belongs_to"``, ``"related_to"``). weight Numeric weight/strength of the relationship (0.0–1.0). metadata Arbitrary key-value metadata. Examples -------- ```python import talk_box as tb edge = tb.Edge( source="doc-001", target="entity-python", relation="mentions", weight=0.9, ) edge.relation # "mentions" ``` NodeType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) Type of a knowledge graph node. Values ------ DOCUMENT A source document (file, note, web page). ENTITY A named entity extracted from documents (person, org, concept). TOPIC A topic or category used for classification. Examples -------- ```python import talk_box as tb tb.NodeType.DOCUMENT tb.NodeType.ENTITY tb.NodeType.TOPIC ``` cosine_similarity(a: 'list[float]', b: 'list[float]') -> 'float' Compute cosine similarity between two vectors. Parameters ---------- a First vector. b Second vector. Returns ------- float Cosine similarity in [-1, 1]. Examples -------- ```python import talk_box as tb tb.cosine_similarity([1, 0, 0], [1, 0, 0]) # 1.0 tb.cosine_similarity([1, 0, 0], [0, 1, 0]) # 0.0 ``` ## KnowledgeGraph Methods Methods for the KnowledgeGraph class add_node(self, node: 'Node') -> 'None' Add a node to the graph, or update it if the ID already exists. Parameters ---------- node The node to add or update. Examples -------- ```python kg.add_node(tb.Node( id="topic-ml", node_type=tb.NodeType.TOPIC, name="Machine Learning", )) ``` get_node(self, node_id: 'str') -> 'Node | None' Get a node by ID. Parameters ---------- node_id The node identifier. Returns ------- Node | None The node, or ``None`` if not found. delete_node(self, node_id: 'str') -> 'bool' Delete a node and all its edges. Parameters ---------- node_id The node to remove. Returns ------- bool ``True`` if the node existed and was deleted. list_nodes(self, *, node_type: 'NodeType | None' = None, limit: 'int' = 100) -> 'list[Node]' List nodes, optionally filtered by type. Parameters ---------- node_type Filter to a specific node type. limit Maximum number of nodes to return. Returns ------- list[Node] Matching nodes ordered by name. node_count(self, *, node_type: 'NodeType | None' = None) -> 'int' Count nodes in the graph. Parameters ---------- node_type If provided, count only nodes of this type. Returns ------- int Number of matching nodes. add_edge(self, edge: 'Edge') -> 'None' Add an edge to the graph, or update it if the key already exists. Parameters ---------- edge The edge to add or update. The (source, target, relation) triple is the primary key. Raises ------ KeyError If source or target node does not exist. get_edges(self, node_id: 'str', *, direction: 'str' = 'both', relation: 'str | None' = None) -> 'list[Edge]' Get edges connected to a node. Parameters ---------- node_id The node to query edges for. direction ``"outgoing"``, ``"incoming"``, or ``"both"`` (default). relation Optional filter by relation type. Returns ------- list[Edge] Matching edges. delete_edge(self, source: 'str', target: 'str', relation: 'str') -> 'bool' Delete a specific edge. Parameters ---------- source Source node ID. target Target node ID. relation The relation label. Returns ------- bool ``True`` if the edge existed and was deleted. edge_count(self) -> 'int' Count edges in the graph. Returns ------- int Total number of edges. neighbors(self, node_id: 'str', *, relation: 'str | None' = None, direction: 'str' = 'outgoing') -> 'list[Node]' Get neighboring nodes connected by edges. Parameters ---------- node_id The starting node. relation Optional filter by relation type. direction ``"outgoing"`` (default), ``"incoming"``, or ``"both"``. Returns ------- list[Node] Connected nodes. search(self, query: 'str', *, node_type: 'NodeType | None' = None, limit: 'int' = 20) -> 'list[Node]' Search nodes by name or content (case-insensitive substring match). Parameters ---------- query Text to search for in node names and content. node_type Optional filter by node type. limit Maximum results to return. Returns ------- list[Node] Matching nodes, name matches ranked first. Examples -------- ```python results = kg.search("python", node_type=tb.NodeType.ENTITY) ``` stats(self) -> 'dict[str, Any]' Get summary statistics about the graph. Returns ------- dict[str, Any] Counts of nodes (total and per type) and edges. Examples -------- ```python kg.stats() # {"nodes": 42, "edges": 87, "documents": 10, "entities": 25, "topics": 7} ``` health(self) -> 'dict[str, Any]' Get health metrics for the graph. Reports orphan nodes (no edges), isolated clusters, and embedding coverage. Returns ------- dict[str, Any] Health metrics including orphan count and embedding coverage. Examples -------- ```python report = kg.health() report["orphan_nodes"] # 3 report["embedding_coverage"] # 0.85 ``` pending_questions(self, *, refresh: 'bool' = True, sort_by: 'str' = 'confusion_impact', limit: 'int | None' = None) -> 'list[Any]' Get pending enrichment questions for this knowledge graph. Detects ambiguities (duplicate names, factual conflicts, weak relationships) and returns structured questions sorted by confusion impact. Parameters ---------- refresh If ``True`` (default), run built-in detectors to find new questions before returning. sort_by Sort field: ``"confusion_impact"`` (default, descending) or ``"created_at"`` (ascending, oldest first). limit Maximum questions to return. Defaults to the queue's ``max_per_session`` (7). Returns ------- list[EnrichmentQuestion] Pending questions sorted by priority. Examples -------- ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") # ... add nodes and edges ... questions = kg.pending_questions() for q in questions: print(f"[{q.confusion_impact:.2f}] {q.text}") ``` Skip detection and return only existing questions: ```python questions = kg.pending_questions(refresh=False) ``` answer_question(self, question_id: 'str', *, choice: 'int | None' = None, freeform: 'str | None' = None) -> 'Any | None' Answer a pending enrichment question. At least one of ``choice`` or ``freeform`` must be provided. Parameters ---------- question_id ID of the question to answer. choice Index of the selected option. freeform Freeform text answer. Returns ------- EnrichmentQuestion | None The updated question, or ``None`` if not found or not pending. Raises ------ ValueError If neither ``choice`` nor ``freeform`` is provided, or ``choice`` is out of range. Examples -------- ```python questions = kg.pending_questions() kg.answer_question(questions[0].id, choice=0) kg.answer_question(questions[1].id, freeform="It's the API migration") ``` dismiss_question(self, question_id: 'str') -> 'Any | None' Dismiss a pending enrichment question without answering. Parameters ---------- question_id ID of the question to dismiss. Returns ------- EnrichmentQuestion | None The dismissed question, or ``None`` if not found. Examples -------- ```python kg.dismiss_question("eq-a1b2c3d4") ``` question_stats(self) -> 'dict[str, int]' Get summary statistics for the enrichment question queue. Returns ------- dict[str, int] Counts by status (total, pending, answered, dismissed, expired). Examples -------- ```python kg.question_stats() # {"total": 5, "pending": 3, "answered": 1, ...} ``` clear(self) -> 'None' Delete all nodes and edges from the graph. close(self) -> 'None' Close the database connection. __repr__(self) -> 'str' ## KG Visualization Render knowledge graphs as Mermaid diagrams or interactive HTML pages. VisNode(id: 'str', label: 'str', node_type: 'str', color: 'str' = '#4A90D9', size: 'int' = 20, metadata: 'dict[str, Any]' = ) -> None A node prepared for visualization. Parameters ---------- id Node identifier. label Display label. node_type Node type string. color CSS color for the node. size Relative node size. metadata Extra display metadata. Examples -------- ```python import talk_box as tb vn = tb.VisNode(id="e1", label="Python", node_type="entity", color="#50C878", size=20) vn.label # "Python" ``` VisEdge(source: 'str', target: 'str', label: 'str', weight: 'float' = 1.0, color: 'str' = '#888888') -> None An edge prepared for visualization. Parameters ---------- source Source node ID. target Target node ID. label Edge label (relation). weight Edge weight (affects thickness). color CSS color for the edge. Examples -------- ```python import talk_box as tb ve = tb.VisEdge(source="doc-1", target="e1", label="mentions", weight=0.9) ve.label # "mentions" ``` VisGraph(nodes: 'list[VisNode]' = , edges: 'list[VisEdge]' = , title: 'str' = 'Knowledge Graph') -> None A complete graph prepared for visualization. Parameters ---------- nodes Visualization nodes. edges Visualization edges. title Graph title. Examples -------- ```python import talk_box as tb graph = tb.prepare_vis_graph(kg) graph.node_count # 10 graph.edge_count # 15 ``` VisGraph.node_count Number of nodes in the visualization. Examples -------- ```python graph.node_count # 10 ``` VisGraph.edge_count Number of edges in the visualization. Examples -------- ```python graph.edge_count # 15 ``` to_dict(self) -> 'dict[str, Any]' Serialize to a dictionary. Examples -------- ```python d = graph.to_dict() len(d["nodes"]) # 10 ``` prepare_vis_graph(kg: 'KnowledgeGraph', *, max_nodes: 'int' = 200, node_type: 'NodeType | None' = None, color_by: 'str' = 'type', title: 'str' = 'Knowledge Graph') -> 'VisGraph' Prepare a knowledge graph for visualization. Converts nodes and edges into visualization-ready dataclasses with computed colors, sizes, and labels. Parameters ---------- kg The knowledge graph to visualize. max_nodes Maximum number of nodes to include. node_type If provided, only include nodes of this type. color_by Color scheme: ``"type"`` (by node type) or ``"freshness"`` (by update recency). title Title for the visualization. Returns ------- VisGraph A visualization-ready graph. Examples -------- ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") # ... add nodes and edges ... graph = tb.prepare_vis_graph(kg, color_by="freshness") graph.node_count ``` to_mermaid(kg: 'KnowledgeGraph', *, direction: 'str' = 'LR', max_nodes: 'int' = 100, max_label_length: 'int' = 30, show_weights: 'bool' = True, node_type: 'NodeType | None' = None) -> 'str' Render a knowledge graph as a Mermaid diagram string. Produces a Mermaid ``graph`` definition suitable for rendering in Markdown, Quarto documents, or any Mermaid-compatible viewer. Parameters ---------- kg The knowledge graph to render. direction Graph direction: ``"LR"`` (left-right), ``"TB"`` (top-bottom), ``"RL"``, or ``"BT"``. max_nodes Maximum number of nodes to include (default 100). max_label_length Truncate node labels longer than this. show_weights If ``True``, annotate edges with their weight. node_type If provided, only include nodes of this type. Returns ------- str A valid Mermaid graph definition. Examples -------- ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") kg.add_node(tb.Node(id="doc-1", node_type=tb.NodeType.DOCUMENT, name="README")) kg.add_node(tb.Node(id="e-py", node_type=tb.NodeType.ENTITY, name="Python")) kg.add_edge(tb.Edge(source="doc-1", target="e-py", relation="mentions")) print(tb.to_mermaid(kg)) ``` to_html(kg: 'KnowledgeGraph', *, max_nodes: 'int' = 200, node_type: 'NodeType | None' = None, color_by: 'str' = 'type', title: 'str' = 'Knowledge Graph') -> 'str' Render a knowledge graph as an interactive HTML page. Generates a self-contained HTML file with an SVG-based force-directed graph layout. No external JavaScript dependencies are required. Parameters ---------- kg The knowledge graph to render. max_nodes Maximum nodes to include. node_type If provided, only include nodes of this type. color_by Color scheme: ``"type"`` or ``"freshness"``. title Page title. Returns ------- str Complete HTML document as a string. Examples -------- ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") # ... add nodes ... html_str = tb.to_html(kg, color_by="freshness") ``` visualize(kg: 'KnowledgeGraph', *, output: 'str | Path | None' = None, max_nodes: 'int' = 200, node_type: 'NodeType | None' = None, color_by: 'str' = 'type', title: 'str' = 'Knowledge Graph', open_browser: 'bool' = True) -> 'Path' Render a knowledge graph and open it in the browser. Writes an interactive HTML file and optionally opens it in the default browser. Parameters ---------- kg The knowledge graph to visualize. output Path for the HTML file. Defaults to a temporary file. max_nodes Maximum nodes to include. node_type If provided, only include nodes of this type. color_by Color scheme: ``"type"`` or ``"freshness"``. title Page title. open_browser If ``True`` (default), open the file in the default browser. Returns ------- Path Path to the generated HTML file. Examples -------- ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") # ... add nodes ... path = tb.visualize(kg, open_browser=False) path # PosixPath('/tmp/talk_box_kg_xxxxx.html') ``` ## Connectors Ingest documents from files, directories, and Apple Notes into the knowledge graph. Document(title: 'str', content: 'str', source: 'str' = '', metadata: 'dict[str, Any]' = ) -> None A document to ingest into the knowledge graph. Parameters ---------- title Human-readable title or filename. content Full text content of the document. source Origin identifier (file path, URL, connector name). metadata Arbitrary key-value metadata (folder, tags, dates, etc.). Examples -------- ```python import talk_box as tb doc = tb.Document( title="README.md", content="# My Project\nThis is a project.", source="/path/to/README.md", ) doc.title # "README.md" ``` Connector(name: 'str') -> 'None' Base class for knowledge graph connectors. Subclasses must implement :meth:`scan` which yields :class:`Document` instances. The connector tracks which documents have been seen so that :meth:`sync` only re-ingests changed content. Parameters ---------- name A short name identifying this connector instance. Examples -------- ```python import talk_box as tb class MyConnector(tb.Connector): def __init__(self): super().__init__(name="my-source") def scan(self): yield tb.Document(title="hello", content="world") ``` scan(self) -> 'Iterator[Document]' Yield documents from this source. Each call should yield all currently available documents. The sync engine uses content hashes to detect changes. MarkdownDir(path: 'str | Path', *, name: 'str' = 'markdown-dir') -> 'None' Ingest Markdown files from a directory. Recursively scans a directory for ``.md`` and ``.markdown`` files and yields each as a :class:`Document`. Parameters ---------- path Path to the directory to scan. name Connector name (defaults to ``"markdown-dir"``). Examples -------- ```python import talk_box as tb connector = tb.MarkdownDir("~/Documents/notes/") for doc in connector.scan(): print(doc.title) ``` scan(self) -> 'Iterator[Document]' Yield Markdown documents from the directory tree. DirectoryConnector(path: 'str | Path', *, extensions: 'list[str] | None' = None, name: 'str' = 'directory') -> 'None' Ingest text-based files from a directory by extension. Scans a directory recursively and yields files matching the given extensions as :class:`Document` objects. Binary files (e.g. PDF) are skipped with a note in metadata — full PDF extraction is left to enrichment plugins. Parameters ---------- path Path to the directory to scan. extensions File extensions to include (e.g. ``[".txt", ".md", ".py"]``). Defaults to ``[".txt", ".md"]``. name Connector name (defaults to ``"directory"``). Examples -------- ```python import talk_box as tb connector = tb.DirectoryConnector( "~/Documents/work/", extensions=[".txt", ".md", ".py"], ) for doc in connector.scan(): print(doc.title, len(doc.content)) ``` scan(self) -> 'Iterator[Document]' Yield documents from the directory tree. AppleNotes(*, folder: 'str | None' = None, tag: 'str | None' = None, db_path: 'str | Path | None' = None, name: 'str' = 'apple-notes') -> 'None' Ingest notes from macOS Apple Notes (read-only). Reads from the NoteStore.sqlite database. Notes are **opt-in**: only notes in a specific folder or containing a tag are ingested. Parameters ---------- folder Only ingest notes from this Apple Notes folder name (e.g. ``"Talk Box"``). Case-insensitive. tag Only ingest notes containing this tag in the body (e.g. ``"#tb-knowledge"``). Case-insensitive. db_path Override the database path (useful for testing). name Connector name (defaults to ``"apple-notes"``). Notes ----- Apple Notes' SQLite schema is undocumented and may change between macOS versions. This connector is best-effort and read-only. At least one of ``folder`` or ``tag`` must be provided to prevent accidental ingestion of all notes. Examples -------- ```python import talk_box as tb connector = tb.AppleNotes(folder="Talk Box") for doc in connector.scan(): print(doc.title) ``` scan(self) -> 'Iterator[Document]' Yield documents from Apple Notes matching the folder/tag filter. SyncResult(added: 'int' = 0, updated: 'int' = 0, unchanged: 'int' = 0) -> None Result of a connector sync operation. Parameters ---------- added Number of new documents added. updated Number of existing documents updated (content changed). unchanged Number of documents skipped (content unchanged). Examples -------- ```python result.added # 5 result.updated # 2 result.unchanged # 10 result.total # 17 ``` SyncResult.total Total documents processed. connector(fn: 'Callable[[], Iterator[Document]]') -> 'Connector' Create a connector from a generator function. The decorated function should yield :class:`Document` instances. Parameters ---------- fn A callable that returns an iterator of documents. Returns ------- Connector A connector wrapping the function. Examples -------- ```python import talk_box as tb @tb.connector def my_source(): yield tb.Document(title="hello", content="world") for doc in my_source.scan(): print(doc.title) ``` sync(kg: 'Any', *connectors: 'Connector', node_prefix: 'str' = 'doc') -> 'SyncResult' Sync documents from connectors into a knowledge graph. Performs incremental sync: only adds or updates documents whose content has changed since the last sync. Optionally removes nodes whose source documents no longer exist. Parameters ---------- kg A :class:`~talk_box.knowledge_graph.KnowledgeGraph` instance. *connectors One or more :class:`Connector` instances to sync from. node_prefix Prefix for generated node IDs (default ``"doc"``). Returns ------- SyncResult Summary of what was added, updated, and unchanged. Examples -------- ```python import talk_box as tb kg = tb.KnowledgeGraph(":memory:") md = tb.MarkdownDir("~/notes/") result = tb.sync(kg, md) result.added # 5 result.updated # 2 ``` ## Enrichment Extract entities, topics, relationships, and summaries from documents in the knowledge graph. ExtractedEntity(name: 'str', entity_type: 'str' = 'unknown', mentions: 'int' = 1, metadata: 'dict[str, Any]' = ) -> None An entity extracted from a document. Parameters ---------- name The entity name (e.g. ``"Sarah Chen"``). entity_type Category such as ``"person"``, ``"organization"``, ``"technology"``, ``"project"``, ``"date"``. mentions Number of times the entity appears in the source document. metadata Extra information about the entity (role, description, etc.). Examples -------- ```python import talk_box as tb entity = tb.ExtractedEntity( name="Sarah Chen", entity_type="person", mentions=3, metadata={"role": "Tech Lead"}, ) entity.name # "Sarah Chen" ``` ExtractedRelationship(source: 'str', target: 'str', relation: 'str' = 'related_to', weight: 'float' = 1.0, metadata: 'dict[str, Any]' = ) -> None A relationship extracted between two entities. Parameters ---------- source Name of the source entity. target Name of the target entity. relation The relationship label (e.g. ``"works_on"``, ``"mentioned_with"``). weight Confidence or strength of the relationship (0.0–1.0). metadata Extra context about the relationship. Examples -------- ```python import talk_box as tb rel = tb.ExtractedRelationship( source="Sarah Chen", target="API Migration", relation="concerned_about", ) ``` EnrichmentResult(entities: 'list[ExtractedEntity]' = , topics: 'list[str]' = , relationships: 'list[ExtractedRelationship]' = , summary: 'str' = '', metadata: 'dict[str, Any]' = ) -> None Complete enrichment output for a single document. Combines all extracted information: entities, topics, relationships, and an optional summary. Parameters ---------- entities Entities found in the document. topics Topic labels assigned to the document. relationships Relationships between entities. summary A short summary of the document content. metadata Additional enrichment metadata (model used, timing, etc.). Examples -------- ```python result = tb.EnrichmentResult( entities=[tb.ExtractedEntity(name="Python", entity_type="technology")], topics=["programming", "open-source"], summary="An overview of Python's key features.", ) result.entity_names # ["Python"] ``` EnrichmentResult.entity_names Names of all extracted entities. EnrichmentResult.entity_count Number of extracted entities. EnrichmentResult.topic_count Number of assigned topics. EnrichmentResult.relationship_count Number of extracted relationships. EnrichmentPipeline(enrich_fn: 'EnrichmentFn', entity_prefix: 'str' = 'entity', topic_prefix: 'str' = 'topic') -> None Configurable pipeline for enriching documents in a knowledge graph. The pipeline applies an enrichment function to document nodes and creates entity nodes, topic nodes, and relationship edges in the graph. Enrichment is incremental: documents are only re-enriched when their content changes. Parameters ---------- enrich_fn A callable ``(title, content) -> EnrichmentResult`` that performs the actual extraction. This is where LLM calls happen. entity_prefix Prefix for generated entity node IDs. topic_prefix Prefix for generated topic node IDs. Examples -------- ```python import talk_box as tb def my_enricher(title: str, content: str) -> tb.EnrichmentResult: # Call your LLM here return tb.EnrichmentResult( entities=[tb.ExtractedEntity(name="Python", entity_type="technology")], topics=["programming"], summary="A document about Python.", ) pipeline = tb.EnrichmentPipeline(enrich_fn=my_enricher) kg = tb.KnowledgeGraph(":memory:") # ... add document nodes via sync() ... result = pipeline.run(kg) result.enriched # number of documents enriched ``` run(self, kg: 'Any', *, limit: 'int' = 100, force: 'bool' = False) -> 'PipelineResult' Run enrichment on document nodes in the knowledge graph. Parameters ---------- kg A :class:`~talk_box.knowledge_graph.KnowledgeGraph` instance. limit Maximum number of documents to enrich per run. force If ``True``, re-enrich all documents regardless of whether they've been enriched before. Returns ------- PipelineResult Summary of enrichment activity. PipelineResult(enriched: 'int' = 0, skipped: 'int' = 0, entities_created: 'int' = 0, topics_created: 'int' = 0, edges_created: 'int' = 0) -> None Result of running the enrichment pipeline. Parameters ---------- enriched Number of documents that were enriched. skipped Number of documents skipped (already enriched, unchanged). entities_created Number of new entity nodes created. topics_created Number of new topic nodes created. edges_created Number of edges created (mentions, belongs_to, relationships). Examples -------- ```python result = pipeline.run(kg) result.enriched # 5 result.entities_created # 12 result.topics_created # 8 ``` PipelineResult.total Total documents processed (enriched + skipped). EnrichmentConfig(add_related_docs: 'int' = 3, add_entity_context: 'bool' = True, add_temporal_context: 'bool' = False) -> None Configuration for how enrichment results are applied. Controls how many related documents to include in context, and which enrichment features to enable. Parameters ---------- add_related_docs Number of most-related documents to include as context when building prompts. add_entity_context Whether to include entity descriptions in prompt context. add_temporal_context Whether to include temporal annotations in context. Examples -------- ```python import talk_box as tb config = tb.EnrichmentConfig( add_related_docs=3, add_entity_context=True, ) ``` regex_enricher(title: 'str', content: 'str') -> 'EnrichmentResult' Simple regex-based enrichment (no LLM required). Extracts entities using common patterns (capitalized phrases, hashtags, @-mentions) and assigns basic topics from keywords. Useful as a fallback or for testing. Parameters ---------- title Document title. content Document content. Returns ------- EnrichmentResult Extracted entities and topics. Examples -------- ```python import talk_box as tb result = tb.regex_enricher("Meeting Notes", "Talked to Sarah Chen about Python.") result.entity_names # ["Sarah Chen"] result.topics # [] ``` ## Compliance Export Export conversation transcripts as auditable JSON or HTML files. export_json(capture: 'ConversationCapture', path: 'str | Path', *, metadata: 'dict[str, Any] | None' = None, indent: 'int' = 2) -> 'Path' Export a conversation capture as an auditable JSON file. The output is a structured JSON document with session metadata, a timestamp, and a full event log with ISO 8601 timestamps. Parameters ---------- capture The conversation capture to export. path File path to write the JSON export to. metadata Additional metadata to include in the export header (e.g., `{"reviewer": "Jane Doe", "department": "compliance"}`). indent JSON indentation level (default `2`). Returns ------- Path The path the file was written to. Examples -------- ```python import talk_box as tb capture = tb.ConversationCapture(session_id="audit-001") capture.record_prompt("Summarize the Q4 report.") capture.record_response("Revenue increased 12% year-over-year.", model="openai:gpt-4o") tb.export_json(capture, "audit-001.json", metadata={"reviewer": "Jane Doe"}) ``` export_html(capture: 'ConversationCapture', path: 'str | Path', *, title: 'str' = '', metadata: 'dict[str, Any] | None' = None) -> 'Path' Export a conversation capture as a human-readable HTML transcript. The output is a self-contained HTML file with styled event blocks, suitable for review, printing, or archival. Parameters ---------- capture The conversation capture to export. path File path to write the HTML export to. title Optional title override for the HTML page. metadata Additional metadata to display in the header (e.g., `{"reviewer": "Jane Doe"}`). Returns ------- Path The path the file was written to. Examples -------- ```python import talk_box as tb capture = tb.ConversationCapture(session_id="audit-001") capture.record_prompt("Summarize the Q4 report.") capture.record_response("Revenue increased 12%.", model="openai:gpt-4o") tb.export_html(capture, "transcript.html", metadata={"reviewer": "Jane Doe"}) ``` ## CLI Command-line interface for managing and testing AI assistants. ## Configuration Layered configuration system with profiles, environment overrides, and CLI flags. TalkBoxConfig(default_model: 'str | None' = None, default_persona: 'str | None' = None, guardrails: 'list[str]' = , temperature: 'float | None' = None, favorite_models: 'list[str]' = , favorite_personas: 'list[str]' = , allow_cloud: 'bool' = True, mode: 'TUIMode' = , profiles: 'dict[str, ProfileConfig]' = , knowledge: 'KnowledgeConfig' = , trusted_commands: 'list[str]' = , autonomous: 'AutonomousConfig' = , notifications: 'NotificationsConfig' = , tools: 'list[str]' = ) -> None Complete Talk Box configuration. This is the merged result of all config layers. Individual fields use ``None`` to indicate "not set" (auto-detect or inherit from a lower-priority layer). resolve(self, *, model: 'str | None' = None, persona: 'str | None' = None, profile: 'str | None' = None, temperature: 'float | None' = None) -> 'ResolvedConfig' Resolve effective settings from config + profile + overrides. Parameters ---------- model CLI/API model override. persona CLI/API persona override. profile Named profile to activate (applies its settings before CLI overrides). temperature CLI/API temperature override. Returns ------- ResolvedConfig The final resolved settings. Raises ------ ValueError If the resolved model is blocked by ``allow_cloud``. KeyError If the named profile does not exist. to_dict(self) -> 'dict[str, Any]' validate_model(self, model_string: 'str') -> 'None' Validate that a model string is allowed under the current config. Raises ------ ValueError If the model is a cloud model and ``allow_cloud`` is ``False``. is_cloud_model(self, model_string: 'str') -> 'bool' Check whether a model string refers to a cloud provider. Parameters ---------- model_string A ``provider:model`` string (e.g., ``"anthropic:claude-sonnet-4-6"``). ProfileConfig(name: 'str', model: 'str | None' = None, persona: 'str | None' = None, temperature: 'float | None' = None, guardrails: 'list[str]' = ) -> None A named profile bundling model + persona + settings. to_dict(self) -> 'dict[str, Any]' ResolvedConfig(model: 'str | None' = None, persona: 'str | None' = None, temperature: 'float | None' = None, guardrails: 'list[str]' = , tools: 'list[str]' = ) -> None The final resolved configuration after all layers are merged. TUIMode(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None) TUI display mode. load_config(*, project_dir: 'Path | None' = None, global_path: 'Path | None' = None) -> 'TalkBoxConfig' Load and merge the full config stack. Resolution order (last wins): 1. Built-in defaults (``TalkBoxConfig()`` with no arguments) 2. Global config (``~/.config/talk-box/config.yml``) 3. Project config (``./talk-box.yml``, searched upward from *project_dir*) Layers 4–6 (profile, env vars, CLI flags) are applied later via ``TalkBoxConfig.resolve()``. Parameters ---------- project_dir Directory to start searching for ``talk-box.yml``. Defaults to cwd. global_path Override the global config path (useful for testing). save_config(config: 'TalkBoxConfig', path: 'Path') -> 'None' Write a config to a YAML file. Parameters ---------- config The configuration to save. path Destination file path. load_profile(name: 'str', *, profiles_dir: 'Path | None' = None) -> 'ProfileConfig' Load a named profile from the profiles directory. Parameters ---------- name Profile name (filename without ``.yml`` extension). profiles_dir Override the profiles directory (useful for testing). Raises ------ FileNotFoundError If the profile file does not exist. save_profile(profile: 'ProfileConfig', *, profiles_dir: 'Path | None' = None) -> 'Path' Save a named profile to the profiles directory. Parameters ---------- profile The profile to save. profiles_dir Override the profiles directory (useful for testing). Returns ------- Path The file path where the profile was saved. list_profiles(*, profiles_dir: 'Path | None' = None) -> 'list[str]' List available profile names from the profiles directory. Parameters ---------- profiles_dir Override the profiles directory (useful for testing). ---------------------------------------------------------------------- This is the User Guide documentation for the package. ---------------------------------------------------------------------- ### Introduction Build production AI assistants with battle-tested personas, structured conversations, and built-in quality assurance. What makes Talk Box special is its **Persona Library** and **PromptBuilder** system—approaches to creating AI assistants that work with how AI models actually process information. ## The PromptBuilder Advantage Talk Box's `PromptBuilder` changes how you would create system prompts for LLMs. Instead of writing free-form text, you use focused methods that handle optimization, formatting, and testing automatically. Here's the traditional approach, where you would write the prompt as a string: ```python import talk_box as tb # Traditional approach: basic system prompt bot = tb.ChatBot().model("gpt-4o").system_prompt( "You are a security expert. Review code for vulnerabilities and performance issues." ) response = bot.chat("Review this authentication function...") ``` With the `PromptBuilder` class, you can build a system prompt with a better structure, automatic optimization, and built-in safeguards. Instead of guessing how to write effective prompts, you use methods that are proven to work with AI attention mechanisms: ```python # PromptBuilder approach: structured and optimized structured_prompt = ( tb.PromptBuilder() .persona("senior security engineer", "performance optimization specialist") .core_analysis([ "authentication vulnerabilities", "performance bottlenecks", "code maintainability" ]) .output_format([ "**CRITICAL**: Security issues requiring immediate fixes", "**OPTIMIZE**: Performance improvements with impact estimates", "**REFACTOR**: Code quality recommendations" ]) .avoid_topics(["deployment", "infrastructure"]) .final_emphasis("Security takes priority over performance") ) bot = tb.ChatBot().model("gpt-4o").system_prompt(structured_prompt) ``` The `PromptBuilder` version produces more consistent, higher-quality responses because it organizes information the way AI models process it best. Plus, you can easily modify specific aspects (like changing the persona or adding new analysis areas) without having to carefully edit a potentially large piece of text. ### Why `PromptBuilder` Works Better Understanding the specific advantages of `PromptBuilder` helps you appreciate why it produces better results than traditional prompting approaches. These benefits stem from research-backed design decisions and practical engineering considerations. `PromptBuilder` gives you powerful advantages over traditional prompting: **1. Focused Methods for Each Prompt Component** - `.persona()`: define expertise and perspective - `.core_analysis()`: specify what to analyze - `.output_format()`: control response structure - `.avoid_topics()`: set clear boundaries **2. Automatic Optimization** - handles attention-optimized ordering and formatting - ensures consistent prompt structure across your application - no need to manually format or reorganize text **3. Built-in Testing Integration** - `.avoid_topics()` enables automatic compliance testing - Talk Box knows exactly what your bot should and shouldn't discuss - easy validation with `tb.autotest_avoid_topics()` **4. Reusable and Modular** - modify specific aspects without rewriting entire prompts - copy and adapt existing prompts for new use cases - version control individual prompt components **5. Predictable Results** - same structure produces consistent response quality - less trial-and-error than free-form prompt writing - built on attention mechanism research, not guesswork These advantages compound over time. The more you use `PromptBuilder`, the more you'll appreciate having structured, testable, and maintainable prompts instead of ad-hoc text strings. ## Why Structure Beats Words The science behind `PromptBuilder` comes from understanding how AI models actually process information. Rather than treating prompts like human conversation, `PromptBuilder` leverages research about AI attention mechanisms to create more effective prompts. It's been shown that **how you organize information** matters more than the specific words you use. AI models process prompts through attention mechanisms that: - **front-load critical information** (primacy bias) - **group related concepts** for better understanding - **lose focus** when instructions are scattered - **respond to hierarchical structure** better than flat text `PromptBuilder` automatically structures your prompts to leverage these patterns, which is why it consistently outperforms manual prompt writing. ## Quick Start: Two Ways to Use Talk Box Talk Box offers two approaches depending on your needs and experience level. Start with simple chatbots to get familiar with the framework, then graduate to PromptBuilder for more sophisticated applications. ### Simple Chatbots (Great for Getting Started) The simplest way to use Talk Box is with basic chatbot configuration using presets. This approach gets you up and running quickly with professional-quality chatbots. ```python import talk_box as tb # Create and configure a chatbot bot = ( tb.ChatBot() .model("gpt-4o") .preset("technical_advisor") .temperature(0.3) ) # Start chatting conversation = bot.chat("How do I optimize Python code for performance?") print(conversation.get_last_message().content) ``` Notice the `.preset("technical_advisor")` method. This instantly configures your chatbot with professional behavior patterns optimized for technical discussions. Presets handle the system prompt creation for you, so you don't need to write any prompts manually. ### Structured `PromptBuilder` Route For more sophisticated applications, create custom prompts using PromptBuilder's research-backed methods. This approach gives you maximum control and consistently better results. ```python import talk_box as tb # Build an expert system with structured prompts expert_prompt = ( tb.PromptBuilder() .persona("senior Python performance engineer") .task_context("code optimization consultation") .focus_on(["algorithmic efficiency", "memory usage", "I/O bottlenecks"]) .constraint("provide specific, actionable recommendations with code examples") .output_format(["analysis", "specific optimizations", "code examples"]) ) expert = tb.ChatBot().model("gpt-4o").system_prompt(expert_prompt) response = expert.chat("How do I optimize Python code for performance?") ``` The `PromptBuilder` approach gives you more control, better results, and repeatable quality. Choose the approach that fits your current needs; you can always upgrade from simple chatbots to `PromptBuilder` as your requirements grow. ## Core Components Talk Box is built around four main components that work together to create powerful conversational AI systems. Understanding these components helps you choose the right tools for your specific use case. ### 📝 PromptBuilder: The Heart of Talk Box Create attention-optimized prompts using research-backed cognitive psychology principles. This is what makes Talk Box special—turn mediocre AI responses into expert-level analysis and assistance. ### 🤖 ChatBot: Your Configuration Hub The main entry point for creating chatbots. Configure models, behaviors, and parameters with a chainable API. Works great as a standalone thing or with `PromptBuilder`. ### 💬 Conversation: Smart Message Management Automatic conversation history with multi-turn context. Every chat interaction returns a `Conversation` object with full message history and intelligent context management. ### 🎭 Presets: Instant Specialization Professional behavior templates for common use cases like customer support, technical advisory, and creative writing. These components work together seamlessly. Use them individually or combine them to create exactly the conversational AI experience you need. ## What's In This Guide This guide is organized to take you from beginner to expert with Talk Box. Start with the basics, then dive deep into the features that matter most for your use case. ### Getting Started Get Talk Box installed and understand the fundamentals before diving into advanced features. - [Installation](installation.qmd): set up Talk Box and dependencies ### Prompt Engineering Master the research-backed prompt engineering system that makes Talk Box great. This is where you'll see the biggest improvement in your AI responses, from basic prompts to advanced features like domain vocabulary, conversational pathways, and tool use. - [PromptBuilder](prompt-builder.qmd): start here and learn the research-backed prompt engineering that makes Talk Box so very special - [Domain Vocabulary](vocabulary.qmd): professional terminology management with multilingual support - [Conversational Pathways](pathways.qmd): intelligent conversation flow guidance - [Tool System](tools.qmd): comprehensive guide to creating and using tools ### Core Concepts Understand the fundamental building blocks of Talk Box chatbots and how to configure them for your needs. - [ChatBot Basics](chatbot-basics.qmd): core concepts and basic configuration - [Model Selection](model-selection.qmd): choosing the right AI model - [File Attachments](file-attachments.qmd): working with documents and files ### Testing & Validation Ensure your chatbots behave appropriately and meet your quality standards with built-in testing tools. - [Compliance for Avoiding Topics](testing-avoid-topics.qmd): ensuring your chatbots behave appropriately Each section builds on the previous ones, so you'll develop a comprehensive understanding of how to create production-ready conversational AI systems with Talk Box. ### ChatBot Basics The `ChatBot` class is your main entry point for creating conversational AI applications. It provides a simple, chainable API for configuring behavior and generates `Conversation` objects that manage message history automatically. ## Your First ChatBot Start with the simplest possible chatbot: ```python import talk_box as tb # Create a basic chatbot bot = tb.ChatBot() # Start chatting conversation = bot.chat("Hello! How are you today?") print(conversation.get_last_message().content) ``` ## The Chainable Configuration API Configure your chatbot by chaining methods together: ```python import talk_box as tb # Build a specialized technical advisor tech_bot = (tb.ChatBot() .model("gpt-4o") # Choose the AI model .preset("technical_advisor") # Apply behavior template .temperature(0.3) # Lower randomness for accuracy .max_tokens(1500) # Allow detailed responses .persona("Senior Python developer with 10+ years experience")) # Now use it response = tech_bot.chat("How do I optimize database queries in Django?") ``` ## Core Configuration Methods ### Model Selection Choose which AI model powers your chatbot: ```python # OpenAI models bot = tb.ChatBot().model("gpt-4o") # Best reasoning bot = tb.ChatBot().model("gpt-4o-mini") # Fast and cost-effective # Anthropic models bot = tb.ChatBot().model("claude-sonnet-4-6") # Excellent for creative tasks bot = tb.ChatBot().model("claude-haiku-3.5-20241022") # Fast for simple tasks # Or specify provider explicitly bot = tb.ChatBot().provider_model("anthropic:claude-sonnet-4-6") ``` ::: {.callout-tip} ## Quick Start with Persona Packs For an even faster setup, use `.persona_pack()` to load a pre-built persona with optimized prompts, vocabulary, and behavior: ```python # One-line expert setup bot = tb.ChatBot().persona_pack("code_reviewer") ``` Persona packs bundle a `PromptBuilder` configuration, vocabulary terms, and recommended settings into a single method call. See the Personas documentation for available packs. ::: ### Behavior Presets Apply professional behavior templates instantly: ```python # Customer support chatbot support_bot = tb.ChatBot().preset("customer_support") # Technical advisor for developers tech_bot = tb.ChatBot().preset("technical_advisor") # Creative writing assistant writer_bot = tb.ChatBot().preset("creative_writer") # Data analysis expert analyst_bot = tb.ChatBot().preset("data_analyst") ``` ### Fine-Tuning Behavior Control how your chatbot responds: ```python bot = (tb.ChatBot() .temperature(0.2) # Low randomness (0.0-2.0) .max_tokens(500) # Limit response length .persona("Friendly but professional customer service rep") .avoid(["technical jargon", "complex explanations"])) ``` ## Understanding Conversations Every chat interaction returns a `Conversation` object that manages message history: ```python bot = tb.ChatBot().preset("technical_advisor") # First interaction creates a new conversation conv = bot.chat("What's the difference between lists and tuples in Python?") # Continue the same conversation (maintains context) conv = bot.chat("Which one should I use for storing coordinates?", conversation=conv) # Access the conversation history for message in conv.get_messages(): print(f"{message.role}: {message.content[:50]}...") ``` ### Conversation Management ```python # Start an empty conversation conversation = bot.start_conversation() # Add messages and get responses conversation = bot.continue_conversation(conversation, "Hello!") conversation = bot.continue_conversation(conversation, "Tell me about Python") # Check conversation details print(f"Message count: {conversation.get_message_count()}") print(f"Last message: {conversation.get_last_message().content}") # Filter messages by role user_messages = conversation.get_messages(role="user") assistant_messages = conversation.get_messages(role="assistant") ``` ## Common Patterns ### Quick Task-Specific Bots ```python import talk_box as tb # Code reviewer code_bot = (tb.ChatBot() .model("gpt-4o") .preset("technical_advisor") .temperature(0.2) .persona("Senior engineer focused on code quality and security")) # Creative writer story_bot = (tb.ChatBot() .model("claude-sonnet-4-6") .preset("creative_writer") .temperature(0.8) .persona("Imaginative storyteller with vivid descriptions")) # Data analyst data_bot = (tb.ChatBot() .model("gpt-4o") .preset("data_analyst") .temperature(0.3) .persona("Statistical expert focused on actionable insights")) ``` ### Multi-Turn Conversations ```python # Create a persistent technical consultant consultant = tb.ChatBot().preset("technical_advisor").temperature(0.3) # Start a consulting session session = consultant.chat("I'm building a web API. What framework should I use?") # Continue the conversation with context session = consultant.chat("I'm using Python and need it to handle 1000 requests/second", conversation=session) session = consultant.chat("What about database choice?", conversation=session) session = consultant.chat("How do I handle authentication?", conversation=session) # The consultant remembers the entire conversation context print(f"Full conversation has {session.get_message_count()} messages") ``` ### Dynamic Configuration ```python class SmartChatBot: def __init__(self): self.bot = tb.ChatBot().model("gpt-4o") def answer(self, question: str, domain: str = "general"): # Configure based on the domain if domain == "technical": self.bot.preset("technical_advisor").temperature(0.2) elif domain == "creative": self.bot.preset("creative_writer").temperature(0.8) elif domain == "support": self.bot.preset("customer_support").temperature(0.4) else: self.bot.temperature(0.7) return self.bot.chat(question) # Usage smart_bot = SmartChatBot() tech_response = smart_bot.answer("How do I optimize SQL queries?", "technical") creative_response = smart_bot.answer("Write a short story about AI", "creative") support_response = smart_bot.answer("I can't log into my account", "support") ``` ## Advanced Configuration ### Custom System Prompts For complete control over behavior: ```python # Method 1: Direct string custom_bot = tb.ChatBot().system_prompt(""" You are a senior software architect specializing in microservices. Always consider scalability, security, and maintainability. Provide concrete, actionable recommendations with code examples. """) # Method 2: Using PromptBuilder (recommended for complex prompts) prompt = (tb.ChatBot().prompt_builder() .persona("software architect", "microservices and distributed systems") .core_analysis(["scalability", "security", "maintainability"]) .output_format(["concrete recommendations", "code examples"])) structured_bot = tb.ChatBot().system_prompt(prompt) ``` ### Tool Integration Enable specific capabilities: ```python enhanced_bot = (tb.ChatBot() .model("gpt-4o") .tools(["code_executor", "web_search", "calculator"]) .verbose(True)) # Enable detailed logging ``` ## Error Handling and Debugging ```python import talk_box as tb try: bot = tb.ChatBot().model("gpt-4o") response = bot.chat("Hello!") print(response.get_last_message().content) except Exception as e: print(f"Error: {e}") # Check LLM status status = bot.check_llm_status() if not status["enabled"]: print("Help:", status["help"]) ``` ### Configuration Inspection ```python bot = (tb.ChatBot() .model("gpt-4o") .preset("technical_advisor") .temperature(0.3)) # See current configuration config = bot.get_config_summary() print(f"Model: {config['model']}") print(f"Temperature: {config['temperature']}") print(f"Preset: {config['preset']}") print(f"System prompt: {config['system_prompt'][:100]}...") ``` ## Best Practices ### ✅ Do's - **Chain configurations** for readable setup - **Use presets** as starting points, then customize - **Keep conversations** for multi-turn context - **Match temperature to task** (low for accuracy, high for creativity) - **Test with different models** for optimal performance ### ❌ Don'ts - **Don't mix conversation objects** between different bots - **Don't ignore conversation context** for multi-turn interactions - **Don't use extreme temperatures** without testing - **Don't hardcode API keys** in your code ## Troubleshooting **"No response from chatbot"** - Check if your API key is set correctly - Verify internet connection - Try a simpler model like `gpt-4o-mini` **"Inconsistent responses"** - Lower the temperature (try 0.3 instead of 0.7) - Use more specific prompts or presets - Consider using `PromptBuilder` for structured prompts **"Responses too short/long"** - Adjust `max_tokens` parameter - Modify your persona or system prompt - Use output format specifications in PromptBuilder --- ## Quick Reference **Basic Setup**: `tb.ChatBot().model("gpt-4o").preset("technical_advisor")` **Chat**: `conversation = bot.chat("Your message")` **Continue**: `conversation = bot.chat("Next message", conversation=conversation)` **Access**: `conversation.get_last_message().content` ### Evaluation Prompt engineering is iterative. You change a constraint, swap a model, add a guardrail, and then need to know: did things get better or worse? Talk Box's eval system answers that question by running your chatbot against test queries, scoring responses with a judge model, and surfacing regressions before they reach users. This guide covers single-bot evaluation, variant comparison, regression detection, and reporting. ## Quick Start The simplest eval takes a bot and queries, scores responses on three default dimensions (relevance, safety, instruction adherence), and returns structured results: ```{python} #| eval: false import talk_box as tb bot = tb.ChatBot().persona_pack("code_reviewer") results = tb.eval(bot, queries=["Review this function for issues"]) print(results.summary()) ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("code_reviewer") .mock_responses([ "This function has a potential SQL injection vulnerability on line 3. " "The user input is concatenated directly into the query string. Use " "parameterized queries instead: `cursor.execute('SELECT * FROM users " "WHERE id = ?', (user_id,))`. Additionally, the error handling is too " "broad; catching bare `Exception` masks real bugs." ]) ) judge = ( tb.ChatBot(name="Judge") .mock_responses([ "relevance: 0.92 | Directly addresses code review with specific issues\n" "safety: 1.0 | No harmful content\n" "instruction_adherence: 0.88 | Follows code review persona constraints well" ]) ) results = tb.eval(bot, queries=["Review this function for issues"], judge=judge) print(results.summary()) ``` The summary shows scores per variant per dimension, making it easy to see where a bot excels and where it falls short. ## How It Works The eval pipeline has three stages: 1. **Run**: Each query is sent to the bot via `.chat()`. The response and timing are captured. 2. **Judge**: A separate judge model scores each response on the requested dimensions (0.0 to 1.0). 3. **Aggregate**: Scores are collected into an `EvalResults` object with reporting and analysis methods. The judge model receives the query, the bot's response, and persona context (role, constraints, avoid topics) so it can assess instruction adherence meaningfully. ## Scoring Dimensions Talk Box ships with six scoring dimensions. By default, evaluations use relevance, safety, and instruction adherence: | Dimension | What It Measures | |-----------|-----------------| | `relevance` | Is the response on-topic and directly helpful? | | `safety` | Is it free from harmful or inappropriate content? | | `instruction_adherence` | Does it follow the persona's constraints? | | `tone` | Does it match the expected communication style? | | `completeness` | Does it address all aspects of the query? | | `conciseness` | Is it appropriately brief without padding? | You can select any subset for evaluation: ```{python} #| eval: false import talk_box as tb results = tb.eval( tb.ChatBot().persona_pack("financial_advisor"), queries=["How should I start saving for retirement?"], dimensions=[ tb.EvalDimension.RELEVANCE, tb.EvalDimension.TONE, tb.EvalDimension.COMPLETENESS, tb.EvalDimension.CONCISENESS, ], ) ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("financial_advisor") .mock_responses([ "Start with an emergency fund covering 3-6 months of expenses. " "Then contribute to your employer's 401(k) up to the match. " "After that, open a Roth IRA for tax-free growth." ]) ) judge = ( tb.ChatBot(name="Judge") .mock_responses([ "relevance: 0.95 | Directly answers the retirement savings question\n" "tone: 0.90 | Professional and approachable\n" "completeness: 0.80 | Covers basics but could mention asset allocation\n" "conciseness: 0.92 | Clear and focused without filler" ]) ) results = tb.eval( bot, queries=["How should I start saving for retirement?"], dimensions=[ tb.EvalDimension.RELEVANCE, tb.EvalDimension.TONE, tb.EvalDimension.COMPLETENESS, tb.EvalDimension.CONCISENESS, ], judge=judge, ) for r in results: for s in r.scores: print(f" {s.dimension.value}: {s.score:.2f} | {s.explanation}") ``` ## Comparing Variants The most powerful use of eval is comparing two or more bot configurations side by side. Change a constraint, add a guardrail, swap a model, then measure the impact: ```{python} #| eval: false import talk_box as tb results = tb.eval( variants={ "baseline": tb.ChatBot().persona_pack("code_reviewer"), "with_citations": ( tb.ChatBot() .persona_pack("code_reviewer") .guardrail(tb.must_cite_sources()) ), }, queries=[ "Is this code vulnerable to SQL injection?", "How would you refactor this function?", ], judge="anthropic:claude-sonnet-4-6", ) # See per-variant scores for variant, scores in results.scores_by_variant().items(): print(f"{variant}: {scores}") ``` ```{python} #| echo: false import talk_box as tb baseline = tb.ChatBot().persona_pack("code_reviewer").mock_responses([ "Yes, the code concatenates user input directly into SQL. Use parameterized queries.", "Extract the validation logic into a separate function for reusability.", ]) with_citations = ( tb.ChatBot() .persona_pack("code_reviewer") .guardrail(tb.must_cite_sources()) .mock_responses([ "Yes, this is vulnerable (OWASP A03:2021). Use parameterized queries [1].", "Extract validation per the Single Responsibility Principle (Martin, 2003).", ]) ) judge = tb.ChatBot(name="Judge").mock_responses([ "relevance: 0.88 | Identifies the issue\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.80 | Good but no citations", "relevance: 0.85 | Solid refactoring advice\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.75 | Missing citation references", "relevance: 0.90 | Identifies issue with OWASP reference\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.92 | Includes citation as required", "relevance: 0.87 | Good advice with principle reference\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.90 | Cites source material", ]) results = tb.eval( variants={"baseline": baseline, "with_citations": with_citations}, queries=[ "Is this code vulnerable to SQL injection?", "How would you refactor this function?", ], judge=judge, ) for variant, scores in results.scores_by_variant().items(): print(f"{variant}: {scores}") ``` The variant comparison shows exactly how adding the `must_cite_sources()` guardrail affects instruction adherence scores, while verifying that relevance and safety don't regress. ## Regression Detection When updating a persona or adding guardrails, you want confidence that quality didn't drop. The `eval_regression()` function compares a "before" and "after" version and flags any dimension where scores drop below a threshold: ```{python} #| eval: false import talk_box as tb before = tb.ChatBot().persona_pack("customer_support_tier1") after = ( tb.ChatBot() .persona_pack("customer_support_tier1") .guardrail(tb.max_response_length(100)) # Might hurt completeness ) results = tb.eval_regression( before=before, after=after, queries=["How do I reset my password?", "What's your return policy?"], threshold=0.05, ) regressions = results.regressions(baseline="before", threshold=0.05) if regressions: print("Regressions detected:") for variant, dims in regressions.items(): for dim, delta in dims.items(): print(f" {dim}: {delta:+.2f}") else: print("No regressions. Safe to deploy.") ``` ```{python} #| echo: false import talk_box as tb before = ( tb.ChatBot() .persona_pack("customer_support_tier1") .mock_responses([ "To reset your password, go to Settings > Security > Change Password. " "You'll need to verify your email first.", "Our return policy allows returns within 30 days of purchase with " "original receipt. Items must be in unused condition.", ]) ) after = ( tb.ChatBot() .persona_pack("customer_support_tier1") .guardrail(tb.max_response_length(100)) .mock_responses([ "To reset your password, go to Settings > Security > Change Password. " "You'll need to verify your email first.", "Our return policy allows returns within 30 days of purchase with " "original receipt. Items must be in unused condition.", ]) ) judge = tb.ChatBot(name="Judge").mock_responses([ "relevance: 0.90 | Helpful step-by-step\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.85 | Good support tone", "relevance: 0.88 | Clear policy explanation\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.82 | Professional", "relevance: 0.75 | Truncated, missing details\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.80 | Tone ok but incomplete", "relevance: 0.70 | Cut off too early\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.78 | Abrupt ending", ]) results = tb.eval_regression( before=before, after=after, queries=["How do I reset my password?", "What's your return policy?"], judge=judge, threshold=0.05, ) regressions = results.regressions(baseline="before", threshold=0.05) if regressions: print("Regressions detected:") for variant, dims in regressions.items(): for dim, delta in dims.items(): print(f" {dim}: {delta:+.2f}") else: print("No regressions. Safe to deploy.") ``` This pattern is ideal for CI pipelines: run `eval_regression()` on every PR that touches persona definitions or guardrail configuration, and fail the build if quality drops. ## Model Comparison with `eval_suite()` When you want to know which model runs a persona best, `eval_suite()` does the heavy lifting. Give it a persona name and a list of models; it creates a bot variant for each model, runs every query through all of them, and returns combined results: ```{python} #| eval: false import talk_box as tb results = tb.eval_suite( "code_reviewer", models=[ "anthropic:claude-sonnet-4-6", "github:gpt-4o", ], judge="anthropic:claude-sonnet-4-6", ) results.to_great_table() ``` ```{python} #| echo: false import talk_box as tb bot_a = ( tb.ChatBot(name="Eval: code_reviewer @ anthropic:claude-sonnet-4-6") .persona_pack("code_reviewer") .mock_responses([ "This function has a potential null pointer dereference on line 5. " "Always validate the return value of `get_user()` before accessing " "its attributes.", ]) ) bot_b = ( tb.ChatBot(name="Eval: code_reviewer @ github:gpt-4o") .persona_pack("code_reviewer") .mock_responses([ "The code looks mostly fine. You could add a null check on line 5.", ]) ) judge = tb.ChatBot(name="Judge").mock_responses([ "relevance: 0.92 | Identifies the exact issue with line reference\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.90 | Thorough review with actionable fix", "relevance: 0.75 | Identifies the issue but lacks detail\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.68 | Too brief for a code review", ]) results = tb.eval( variants={ "anthropic:claude-sonnet-4-6": bot_a, "github:gpt-4o": bot_b, }, queries=["Review this function for issues"], judge=judge, ) results.config["persona"] = "code_reviewer" results.config["models"] = [ "anthropic:claude-sonnet-4-6", "github:gpt-4o", ] results.config["type"] = "suite" for variant, scores in results.scores_by_variant().items(): dims = " | ".join(f"{d}: {s:.2f}" for d, s in scores.items()) print(f"{variant}: {dims}") ``` Each variant in the results is named after its model string, so it's immediately clear which model performed best on each dimension. ### Persona default guards By default, `eval_suite()` applies the persona's default guards (if any are defined). To evaluate the raw model without guardrails, pass `default_guards=False`: ```{python} #| eval: false results = tb.eval_suite( "financial_advisor", models=["anthropic:claude-sonnet-4-6", "github:gpt-4o"], default_guards=False, judge="anthropic:claude-sonnet-4-6", ) ``` ### GitHub Copilot models Talk Box supports the `github` provider through chatlas' `ChatGithub`, which gives you access to a wide range of models through your GitHub Copilot subscription. Use the `github:` prefix in model strings: ```{python} #| eval: false results = tb.eval_suite( "code_reviewer", models=[ "github:gpt-4o", "github:o3-mini", "github:claude-sonnet-4-6", ], judge="anthropic:claude-sonnet-4-6", ) ``` ::: {.callout-note} The `github` provider requires a `GITHUB_TOKEN` environment variable. If you have GitHub Copilot set up locally, this is typically your existing token. ::: ## Scorecard Export After running an evaluation, you can export the results as a JSON scorecard for tracking over time, committing to your repository, or publishing to a docs site: ```{python} #| eval: false results.to_scorecard("scorecards/code_reviewer.json") ``` ```{python} #| echo: false import talk_box as tb results = tb.EvalResults( results=[ tb.EvalResult( variant="anthropic:claude-sonnet-4-6", query="Review this function", response="Potential null pointer on line 5.", scores=[ tb.EvalScore(tb.EvalDimension.RELEVANCE, 0.92, "Identifies issue"), tb.EvalScore(tb.EvalDimension.SAFETY, 1.0, "Safe"), tb.EvalScore( tb.EvalDimension.INSTRUCTION_ADHERENCE, 0.90, "Thorough review", ), ], duration=1.2, ), tb.EvalResult( variant="github:gpt-4o", query="Review this function", response="Code looks fine, add a null check.", scores=[ tb.EvalScore(tb.EvalDimension.RELEVANCE, 0.75, "Brief"), tb.EvalScore(tb.EvalDimension.SAFETY, 1.0, "Safe"), tb.EvalScore( tb.EvalDimension.INSTRUCTION_ADHERENCE, 0.68, "Too brief", ), ], duration=0.8, ), ], config={ "persona": "code_reviewer", "models": ["anthropic:claude-sonnet-4-6", "github:gpt-4o"], "type": "suite", }, ) import json card = results.to_scorecard() print(json.dumps(card, indent=2)) ``` The `eval_suite()` function also accepts a `scorecard_path` parameter for one-shot evaluate-and-export: ```{python} #| eval: false results = tb.eval_suite( "code_reviewer", models=["anthropic:claude-sonnet-4-6", "github:gpt-4o"], judge="anthropic:claude-sonnet-4-6", scorecard_path="scorecards/code_reviewer.json", ) ``` ## Using Persona Test Queries Every persona ships with `test_queries`, which are representative questions that exercise the persona's core capabilities. When you call `eval()` without explicit queries, it automatically uses these: ```{python} #| eval: false import talk_box as tb # Uses code_reviewer's built-in test_queries bot = tb.ChatBot().persona_pack("code_reviewer") results = tb.eval(bot, judge="anthropic:claude-sonnet-4-6") print(f"Evaluated {len(results)} queries") print(f"Overall passed (>0.7): {results.passed()}") ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("code_reviewer") .mock_responses([ "This function lacks input validation.", "The query uses string formatting, making it vulnerable to injection.", "Consider extracting the retry logic into a decorator.", "The loop can be replaced with a list comprehension for clarity.", ]) ) judge = tb.ChatBot(name="Judge").mock_responses([ "relevance: 0.85 | Identifies a real issue\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.80 | Good review feedback", "relevance: 0.92 | Correctly identifies SQL injection\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.88 | Follows security-first priority", "relevance: 0.80 | Reasonable suggestion\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.75 | Could include code example", "relevance: 0.78 | Valid improvement\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.72 | Suggestion without severity level", ]) results = tb.eval(bot, judge=judge) print(f"Evaluated {len(results)} queries") print(f"Overall passed (>0.7): {results.passed()}") ``` This makes it easy to run a quality check on any persona with zero configuration. ## Reporting `EvalResults` supports multiple output formats for analysis and presentation. ### Summary Statistics The `.summary()` method returns a dictionary with aggregate scores: ```{python} #| eval: false import talk_box as tb results = tb.eval(bot, queries=["How do I sort a list?"]) summary = results.summary() print(f"Variants: {summary['variants']}") print(f"Dimensions: {summary['dimensions']}") print(f"Overall scores: {summary['overall_scores']}") ``` ### Great Tables Report For visual comparison, `.to_great_table()` produces a formatted table showing mean scores per variant per dimension: ```{python} #| eval: false import talk_box as tb results = tb.eval( variants={"v1": bot_v1, "v2": bot_v2}, queries=queries, ) results.to_great_table() ``` ### DataFrame Export For custom analysis, `.to_dataframe()` exports all results to a pandas DataFrame with one row per (variant, query, dimension) combination: ```{python} #| eval: false import talk_box as tb df = results.to_dataframe() # Group by variant, compute mean scores print(df.groupby("variant")["score"].mean()) ``` ## The Pass/Fail Gate The `.passed()` method checks whether all variants meet a minimum quality threshold. Use this in CI to gate deployments: ```{python} #| eval: false import talk_box as tb bot = tb.ChatBot().persona_pack("customer_support_tier1") results = tb.eval(bot, judge="anthropic:claude-sonnet-4-6") assert results.passed(threshold=0.75), ( f"Bot failed quality gate: {results.summary()['overall_scores']}" ) ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("customer_support_tier1") .mock_responses([ "I'd be happy to help you with that! Let me look into your account.", ]) ) judge = tb.ChatBot(name="Judge").mock_responses([ "relevance: 0.88 | Acknowledges and offers help\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.82 | Friendly support tone" ]) results = tb.eval( bot, queries=["I need help with my order"], judge=judge, ) print(f"Passed (threshold=0.75): {results.passed(threshold=0.75)}") print(f"Passed (threshold=0.95): {results.passed(threshold=0.95)}") ``` A threshold of 0.75 is a reasonable default for most use cases. Raise it for high-stakes personas (financial, medical) and lower it when testing against smaller local models. ## Public Scorecards The `scorecard_table()` and `sweep_table()` functions turn scorecard and sweep JSON files into polished Great Tables with color-coded score cells, ready for embedding in docs, notebooks, or HTML reports. ### Single-Persona Scorecard After running `eval_suite()`, the `.to_scorecard()` output feeds directly into `scorecard_table()`: ```{python} #| eval: false import talk_box as tb # Run evaluation results = tb.eval_suite( "code_reviewer", models=["anthropic:claude-sonnet-4-6", "github:gpt-4o"], judge="anthropic:claude-sonnet-4-6", scorecard_path="scorecards/code_reviewer.json", ) # Render from the saved file tb.scorecard_table("scorecards/code_reviewer.json") ``` Or directly from the in-memory scorecard dict: ```{python} #| eval: false tb.scorecard_table(results.to_scorecard()) ``` ```{python} #| echo: false import talk_box as tb card = { "generated_at": "2025-05-07T12:00:00+00:00", "config": {"persona": "code_reviewer", "judge": "anthropic:claude-sonnet-4-6"}, "variants": { "anthropic:claude-sonnet-4-6": { "dimensions": {"relevance": 0.96, "safety": 1.0, "instruction_adherence": 0.92}, "overall": 0.96, "num_queries": 3, }, "github:gpt-4o": { "dimensions": {"relevance": 0.95, "safety": 1.0, "instruction_adherence": 0.90}, "overall": 0.95, "num_queries": 3, }, }, } tb.scorecard_table(card) ``` ### Sweep Summary After a multi-persona sweep (via `make eval-sweep` or `run_eval_sweep.py`), render the combined results with `sweep_table()`: ```{python} #| eval: false import talk_box as tb tb.sweep_table("scorecards/_sweeps/2025-05-07T12-00-00.json") ``` ```{python} #| echo: false import talk_box as tb sweep = { "generated_at": "2025-05-07T12:00:00+00:00", "models": ["anthropic:claude-sonnet-4-6", "github:gpt-4o"], "judge": "anthropic:claude-sonnet-4-6", "threshold": 0.7, "elapsed_seconds": 120, "passed": 5, "total": 5, "results": [ {"persona": "code_reviewer", "passed": True, "elapsed": 25.1, "scores": {"anthropic:claude-sonnet-4-6": 0.96, "github:gpt-4o": 0.95}}, {"persona": "financial_advisor", "passed": True, "elapsed": 30.2, "scores": {"anthropic:claude-sonnet-4-6": 1.00, "github:gpt-4o": 0.99}}, {"persona": "customer_support_tier1", "passed": True, "elapsed": 22.8, "scores": {"anthropic:claude-sonnet-4-6": 0.97, "github:gpt-4o": 0.96}}, {"persona": "data_analyst", "passed": True, "elapsed": 28.5, "scores": {"anthropic:claude-sonnet-4-6": 0.98, "github:gpt-4o": 0.97}}, {"persona": "technical_writer", "passed": True, "elapsed": 18.3, "scores": {"anthropic:claude-sonnet-4-6": 0.98, "github:gpt-4o": 0.77}}, ], } tb.sweep_table(sweep) ``` Both functions accept either a file path or a dict, so they work seamlessly in scripts, notebooks, and Quarto documents. The tables use a red → yellow → green color scale on score columns, making it easy to spot weak spots at a glance. ## Model Version Comparison When a model provider releases a new version, use `eval_model_update()` to check whether your personas hold up. It runs the same persona against both model versions and flags any dimension that regresses beyond a threshold: ```{python} #| eval: false import talk_box as tb results = tb.eval_model_update( "code_reviewer", before="anthropic:claude-sonnet-4-5", after="anthropic:claude-sonnet-4-6", judge="anthropic:claude-sonnet-4-6", ) # Inspect regressions (dimensions that dropped > 5%) drops = results.regressions() if drops: print("Regressions found:", drops) else: print("No regressions — safe to upgrade!") # Visual comparison results.to_great_table() ``` ```{python} #| echo: false import talk_box as tb bot_before = ( tb.ChatBot() .persona_pack("code_reviewer") .mock_responses(["The function looks correct but could use better naming."]) ) bot_after = ( tb.ChatBot() .persona_pack("code_reviewer") .mock_responses(["The function has good structure. Variable names are clear."]) ) judge = tb.ChatBot(name="Judge").mock_responses([ "relevance: 0.85 | Identifies issue\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.82 | Follows code review format", "relevance: 0.90 | More thorough\n" "safety: 1.0 | Safe\n" "instruction_adherence: 0.88 | Good adherence", ]) results = tb.eval( variants={ "anthropic:claude-sonnet-4-5": bot_before, "anthropic:claude-sonnet-4-6": bot_after, }, queries=["Review this function for issues"], judge=judge, ) drops = results.regressions() if drops: print(f"Regressions found: {drops}") else: print("No regressions — safe to upgrade!") ``` You can also write the comparison to a scorecard for tracking over time: ```{python} #| eval: false results = tb.eval_model_update( "financial_advisor", before="anthropic:claude-sonnet-4-5", after="anthropic:claude-sonnet-4-6", judge="anthropic:claude-sonnet-4-6", scorecard_path="scorecards/model_updates/financial_advisor_4-5_vs_4-6.json", ) tb.scorecard_table(results.to_scorecard()) ``` # File Attachments in Talk Box File attachments enable you to include documents, images, and other files in your AI conversations. This feature is designed for **programmatic single-turn conversations** where you want to analyze, review, or discuss file content with AI models. ## When to Use File Attachments File attachments are ideal for automated workflows and batch processing scenarios: - **Code Review**: analyze source files for bugs, best practices, and improvements - **Document Analysis**: extract insights from PDFs, reports, and documentation - **Data Analysis**: process CSV, JSON, or other data files for trends and patterns - **Content Generation**: use reference materials for context-aware content creation - **Image Analysis**: analyze charts, diagrams, photos with vision-capable models - **Research**: process academic papers, articles, and research materials ## Quick Start ### Basic Usage The simplest way to use file attachments is with a single file. This example shows the complete workflow from setup to getting AI analysis results: ```python import talk_box as tb # Step 1: Create a ChatBot for analysis bot = tb.ChatBot().provider_model("openai:gpt-4o") # Step 2: Attach a file with analysis prompt files = tb.Attachments("report.pdf").with_prompt( "Summarize the key findings in this report." ) # Step 3: Get LLM analysis analysis = bot.chat(files) ``` View the results as an HTML report: ```python analysis ``` ### Multiple Files When you need to analyze related files together, you can attach multiple files in a single operation. This is particularly useful for code reviews, document comparisons, or comprehensive project analysis: ```python import talk_box as tb # Step 1: Create a ChatBot for analysis bot = tb.ChatBot().provider_model("openai:gpt-4o") # Step 4: Analyze multiple related files code_review = tb.Attachments( "talk_box/attachments.py", "talk_box/conversation.py", "tests/test_attachments.py" ).with_prompt( "Review this Python codebase for quality and test coverage." ) # Step 2: Configure bot for technical review reviewer = bot.preset("technical_advisor") # Step 3: Get comprehensive code review review = reviewer.chat(code_review) ``` View the results as an HTML report: ```python review ``` ## File Types Supported Talk Box automatically detects and processes different file types, optimizing the handling based on content. Here's what's currently supported and how each type is best used: | Type | Extensions | Use Cases | |------|-----------|-----------| | **Text** | `.py`, `.js`, `.md`, `.txt`, `.csv`, `.json`, `.xml`, `.yaml` | Code review, documentation, data analysis | | **Images** | `.png`, `.jpg`, `.jpeg`, `.gif`, `.bmp`, `.webp` | Chart analysis, diagram review, visual content | | **PDFs** | `.pdf` | Document analysis, research papers, reports | Unsupported file types are handled gracefully with informative error messages. ## Common Workflows These real-world examples show how to structure file attachment workflows for different scenarios. Each workflow includes error handling, performance considerations, and practical tips: ### 1. Code Review Pipeline This is good for automated code quality checks and pull request reviews: ```python import talk_box as tb from pathlib import Path def review_pull_request(file_paths, context=""): """Review multiple files in a pull request.""" review_prompt = f""" Review these code changes for: 1. Code quality and best practices 2. Potential bugs or security issues 3. Performance implications 4. Test coverage Context: {context} Provide specific, actionable feedback. """ files = tb.Attachments(*file_paths).with_prompt(review_prompt) reviewer = ( tb.ChatBot() .provider_model("openai:gpt-4o") .preset("technical_advisor") .temperature(0.3) # Lower temperature for consistent reviews ) return reviewer.chat(files) # Usage changed_files = ["src/auth.py", "src/database.py", "tests/test_auth.py"] review = review_pull_request(changed_files, "Added OAuth2 authentication") review ``` ### 2. Document Analysis Workflow Ideal for processing reports, research papers, and documentation: ```python def analyze_documents(doc_paths, analysis_type="summary"): """Analyze multiple documents with different analysis types.""" prompts = { "summary": "Provide a concise summary of the key points and conclusions.", "insights": "Extract actionable insights and recommendations.", "comparison": "Compare and contrast the main arguments and findings.", "critique": "Provide a critical analysis of the methodology and conclusions." } files = tb.Attachments(*doc_paths).with_prompt(prompts[analysis_type]) analyst = ( tb.ChatBot() .provider_model("openai:gpt-4o") .temperature(0.4) .max_tokens(2000) ) return analyst.chat(files) # Usage research_papers = ["paper1.pdf", "paper2.pdf", "paper3.pdf"] ``` ```python analyze_documents(research_papers, "summary") ``` ```python analyze_documents(research_papers, "insights") ``` ### 3. Data Analysis Pipeline Process data files with contextual information: ```python def analyze_data_files(data_path, context_files=None, question=""): """Analyze data files with additional context.""" file_list = [data_path] if context_files: file_list.extend(context_files) prompt = f""" Analyze the data and provide: 1. Key trends and patterns 2. Statistical insights 3. Anomalies or outliers 4. Actionable recommendations Question: {question} """ files = tb.Attachments(*file_list).with_prompt(prompt) analyst = ( tb.ChatBot() .provider_model("openai:gpt-4o") .preset("data_analyst") ) return analyst.chat(files) # Usage analysis = analyze_data_files( "sales_q4.csv", context_files=["market_conditions.md", "product_changes.txt"], question="What drove the sales increase in Q4?" ) analysis ``` ### 4. Visual Content Analysis Analyze images, charts, and diagrams: ```python def analyze_visual_content(image_paths, analysis_focus="general"): """Analyze visual content with specific focus areas.""" focus_prompts = { "general": "Describe what you see and identify key elements.", "data": "Extract and analyze any data, charts, or graphs shown.", "design": "Evaluate the design principles, layout, and visual hierarchy.", "technical": "Analyze technical diagrams, architecture, or system designs." } files = tb.Attachments(*image_paths).with_prompt(focus_prompts[analysis_focus]) # Use vision-capable model analyzer = ( tb.ChatBot() .provider_model("openai:gpt-4o") .temperature(0.5) ) return analyzer.chat(files) # Usage charts = ["revenue_chart.png", "user_growth.png", "market_share.png"] data_analysis = analyze_visual_content(charts, "data") data_analysis ``` ## Best Practices for Writing Effective Prompts Follow these guidelines to get the most accurate and useful results from your file attachment workflows. These practices help ensure reliable processing, clear communication with AI models, and robust error handling: The quality of your prompts directly impacts the usefulness of AI analysis. Here are key strategies for writing prompts that generate actionable insights: **Be Specific and Clear** Vague prompts lead to generic responses. Instead, specify exactly what information you need and how you want it presented: ```python import talk_box as tb # Vague files = tb.Attachments("report.pdf").with_prompt("What do you think?") # Specific files = tb.Attachments("report.pdf").with_prompt( "Extract the quarterly revenue figures and identify any significant " "changes compared to the previous quarter. Highlight any risks mentioned." ) ``` **Structure Complex Requests** For multi-part analysis, use numbered lists or clear sections to guide the AI through your requirements systematically: ```python import talk_box as tb files = tb.Attachments("codebase.py").with_prompt(""" Review this code for: 1. Security vulnerabilities (SQL injection, XSS, etc.) 2. Performance bottlenecks 3. Code maintainability issues 4. Missing error handling Provide specific line numbers and improvement suggestions. """) ``` Well-structured prompts not only improve response quality but also make it easier to validate and act on the AI's recommendations. The more specific your request, the more actionable the results will be. ## HTML Display Features When working with file attachments in notebook or other HTML-capable environments, Talk Box provides rich visual representations that make it easy to inspect your attachments at a glance. Simply display an `Attachments` object to see a comprehensive summary: ```python import talk_box as tb # Create attachments with various file types files = tb.Attachments( "analysis.py", "data.csv", "chart.png", "report.pdf" ).with_prompt("Analyze this project data and provide insights.") # Display the HTML representation files # Shows rich HTML summary ``` The HTML display includes several key features that help you understand the state of your attachments: - **File Breakdown**: descriptive icons (📁, 📄, 🖼️) and file sizes help you quickly identify file types and understand processing load - **File Status**: a ❌ mark is shown for files that are either missing or encountered processing errors - **Prompt Preview**: long prompts are displayed in scrollable containers, so you can review your instructions without cluttering the interface This visual feedback is particularly valuable when debugging file processing issues or confirming that your attachments are configured correctly before sending them to an AI model. ## Conclusion File attachments in Talk Box provide a powerful foundation for building AI-powered analysis workflows. Start with simple single-file examples and gradually build more sophisticated batch processing and monitoring systems as your needs grow. ### Guardrails Every production chatbot needs boundaries. A financial advisor shouldn't leak customer email addresses. A support bot shouldn't respond with profanity. A medical assistant must include disclaimers. Talk Box's guardrail system lets you enforce these constraints declaratively, using plain Python functions that intercept messages before and after they reach the LLM. This guide covers how guardrails work, the built-in guards that ship with Talk Box, how to write your own, and patterns for composing them in real-world applications. ## Quick Start Adding guardrails to a chatbot is a single method call per guard. Here's a financial advisor protected by three layers of validation: ```{python} #| eval: false import talk_box as tb # A financial advisor with safety guardrails bot = ( tb.ChatBot() .persona_pack("financial_advisor") .guardrail(tb.no_pii()) .guardrail(tb.max_response_length(500)) .guardrail(tb.disclaimer_required( "This is not financial advice. Consult a licensed professional." )) ) convo = bot.chat("What's a good investment strategy for retirement?") print(convo.get_last_message().content) ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("financial_advisor") .guardrail(tb.no_pii()) .guardrail(tb.max_response_length(500)) .guardrail(tb.disclaimer_required( "This is not financial advice. Consult a licensed professional." )) .mock_responses([ "Based on your described portfolio allocation, a 60/40 stock/bond " "split is a common starting point for moderate risk tolerance. " "Consider reviewing your time horizon and adjusting accordingly." ]) ) convo = bot.chat("What's a good investment strategy for retirement?") print(convo.get_last_message().content) ``` That single chain adds three layers of protection: - **`no_pii()`** strips email addresses, phone numbers, SSNs, and credit card numbers from both inputs and outputs - **`max_response_length(500)`** truncates overly verbose responses - **`disclaimer_required(...)`** appends a legal disclaimer if the model forgets to include one The guards run automatically on every message and no additional code is required at the point of interaction. ::: {.callout-note} The `financial_advisor` persona already ships with `no_pii()` and a disclaimer as [default guards](#persona-default-guards). The example above adds them explicitly to illustrate how manual stacking works. ::: ## How Guards Work At their core, guards are functions that inspect text and decide what to do with it. Each guard takes a string and returns a `GuardResult` indicating whether the text should pass through, be blocked, or be rewritten. You can call any guard directly with `.check()` to see exactly what it does: ```{python} import talk_box as tb # Call a guard directly to see what it does guard = tb.no_pii() # Clean text passes through result = guard.check("What's my account balance?") print(f"Action: {result.action.value}") ``` When PII is present, the guard detects it and rewrites the text with placeholders: ```{python} # Text with PII gets rewritten result = guard.check("My email is john.doe@example.com and my SSN is 123-45-6789") print(f"Action: {result.action.value}") print(f"Cleaned: {result.message}") print(f"Reason: {result.reason}") ``` Every guard returns one of three possible outcomes: | Action | Meaning | What Happens | |--------|---------|--------------| | `passed` | Text is fine | Continues unchanged to the next guard | | `blocked` | Text is rejected | Pipeline stops immediately; user sees a block message | | `rewritten` | Text is modified | Modified text continues through remaining guards | This three-outcome model means guards can do more than just accept/reject, they can actively clean up text while still letting the conversation continue. ## The Guard Pipeline When you attach multiple guards to a chatbot, they form a pipeline. Guards execute sequentially in the order you added them. If one guard rewrites the text, the next guard sees the rewritten version. If any guard blocks, the pipeline short-circuits and later guards never run. This ordering is important. The example below shows a pipeline where PII is stripped first (so keyword checks don't accidentally match on email domains), then keywords are checked, then length is enforced, and finally a disclaimer is appended: ```{python} import talk_box as tb # Pipeline order matters bot = ( tb.ChatBot() .guardrail(tb.no_pii()) # 1. Strip PII first .guardrail(tb.keyword_block(["confidential"])) # 2. Then check for keywords .guardrail(tb.max_response_length(200)) # 3. Then enforce length .guardrail(tb.disclaimer_required("AI-generated content.")) # 4. Add disclaimer ) # Check what guards are attached for guard in bot._guard_pipeline.guards: print(f" {guard.name} (phase: {guard.phase.value})") ``` The output confirms both the order and the phase assignment for each guard. ### Input vs. Output Guards Not every guard should run on both sides of the conversation. A length limit on user input serves a different purpose than a length limit on bot output. Each guard has a **phase** that controls when it fires: | Phase | When It Runs | Use For | |-------|-------------|---------| | `INPUT` | Before the LLM sees the message | Blocking abuse, rejecting long inputs, stripping PII from user messages | | `OUTPUT` | After the LLM responds | Enforcing length, adding disclaimers, checking tone, requiring citations | | `BOTH` | Both directions | PII detection, keyword blocking | The built-in guards come with sensible phase defaults. You can inspect them to understand when each fires: ```{python} import talk_box as tb # max_input_length only runs on user messages guard = tb.max_input_length(100) print(f"Phase: {guard.phase.value}") # disclaimer_required only runs on bot responses guard = tb.disclaimer_required("Disclaimer.") print(f"Phase: {guard.phase.value}") # no_pii runs in both directions guard = tb.no_pii() print(f"Phase: {guard.phase.value}") ``` This phase system means you don't need to worry about output-only guards accidentally interfering with user messages, or vice versa. ## Built-in Guards Talk Box ships with seven guards covering the most common validation needs. Each can be configured through its factory function and used immediately (no subclassing required). ### `no_pii()`: PII Detection and Removal The most critical guard for any production chatbot. It detects email addresses, phone numbers, Social Security numbers, and credit card numbers using pattern matching, and either replaces them with placeholders or blocks the message entirely. In its default mode, PII is replaced with labeled placeholders so the conversation can continue without exposing sensitive data: ```{python} import talk_box as tb # Default: rewrite (replace PII with placeholders) guard = tb.no_pii() result = guard.check("Call me at 555-867-5309 or email alice@company.com") print(result.message) ``` For high-security environments where any PII presence should halt the conversation, use block mode: ```{python} # Strict mode: block messages containing PII guard = tb.no_pii(action="block") result = guard.check("My credit card is 4111 1111 1111 1111") print(f"Action: {result.action.value}") print(f"Reason: {result.reason}") ``` You can extend the built-in patterns with domain-specific identifiers. Here we add detection for medical record numbers: ```{python} # Add custom PII patterns (e.g., medical record numbers) guard = tb.no_pii(patterns=[r"\bMRN-\d{5,}\b"]) result = guard.check("Patient MRN-123456 needs a follow-up") print(result.message) ``` ### `max_response_length()`: Enforce Brevity LLMs tend toward verbosity. This output-only guard truncates responses that exceed a character limit, breaking cleanly at word boundaries and appending an ellipsis: ```{python} import talk_box as tb guard = tb.max_response_length(80) long_response = ( "Machine learning is a subset of artificial intelligence that enables " "systems to learn from data and improve their performance over time " "without being explicitly programmed for every scenario." ) result = guard.check(long_response) print(result.message) ``` This is especially useful for chatbots embedded in space-constrained UIs (chat widgets, mobile apps) where concise answers are essential. ### `tone_check()`: Enforce Communication Style Professional chatbots should sound professional. This guard uses keyword heuristics to detect tone mismatches like casual slang in a professional context, or, overly formal language when the tone is otherwise friendly: ```{python} import talk_box as tb guard = tb.tone_check("professional") # Professional text passes result = guard.check("I appreciate your inquiry. Let me review the details.") print(f"Professional text: {result.action.value}") # Casual text gets blocked result = guard.check("lol yeah that's totally broken bruh, my bad") print(f"Casual text: {result.action.value}") print(f"Reason: {result.reason}") ``` The guard ships with built-in indicator lists for `"professional"`, `"formal"`, and `"casual"` tones, and accepts custom indicator dictionaries for domain-specific needs. ### `disclaimer_required()`: Ensure Legal/Safety Text Regulated industries often require specific disclaimers on every response. This guard checks whether the disclaimer text is present, and appends (or prepends) it if missing. If the model already included it, the text passes through unchanged: ```{python} import talk_box as tb guard = tb.disclaimer_required( "⚠️ This information is for educational purposes only.", position="end" ) # Response without disclaimer: disclaimer added automatically result = guard.check("You should diversify your portfolio across asset classes.") print(result.message) ``` This is a rewriting guard and it never blocks (it only adds the missing text). That makes it safe to stack at the end of any pipeline. ### `must_cite_sources()`: Require Citations For research assistants, knowledge bots, or any context where unsourced claims are unacceptable, this guard blocks responses that don't contain recognizable citations. It detects URLs, bracketed references like `[1]`, footnote markers, and author-year notation: ```{python} import talk_box as tb guard = tb.must_cite_sources(min_citations=1) # No citations: blocked result = guard.check("Studies show that exercise improves cognition.") print(f"Action: {result.action.value}") print(f"Reason: {result.reason}") # With citation: passes result = guard.check("Studies show that exercise improves cognition (Hillman et al., 2008).") print(f"With citation: {result.action.value}") ``` Use `min_citations` to require more than one source for higher-stakes responses. ### `max_input_length()`: Reject Oversized Inputs A defense against prompt stuffing attacks and accidental paste-dumps. This input-only guard blocks messages exceeding a character limit before they reach the LLM (saving tokens and preventing context window overflow): ```{python} import talk_box as tb guard = tb.max_input_length(50) result = guard.check("x" * 100) print(f"Action: {result.action.value}") print(f"Reason: {result.reason}") ``` ### `keyword_block()`: Block Specific Words or Phrases A straightforward blocklist guard. Useful for preventing the chatbot from engaging with certain topics, or for blocking users who attempt to extract sensitive information: ```{python} import talk_box as tb guard = tb.keyword_block( ["password", "api_key", "secret_token"], phase=tb.GuardPhase.INPUT ) result = guard.check("Here's my api_key: sk-abc123") print(f"Action: {result.action.value}") print(f"Reason: {result.reason}") ``` The keyword check is case-insensitive by default. Pass `case_sensitive=True` for exact matching when needed. ## Persona Default Guards Some personas ship with guardrails pre-configured. When you load a persona with `persona_pack()`, its default guards are applied automatically, so you get sensible protection without manually stacking guards. For example, the `financial_advisor` persona auto-applies `no_pii()` and a domain-appropriate disclaimer: ```{python} #| eval: false import talk_box as tb # PII protection and disclaimer are applied automatically bot = tb.ChatBot().persona_pack("financial_advisor") ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("financial_advisor") .mock_responses([ "Start with an emergency fund covering 3-6 months of expenses, " "then contribute to your employer's 401(k) up to the match." ]) ) convo = bot.chat("How should I start saving?") print(convo.get_last_message().content) ``` The following personas include default guards: | Persona | Default Guards | |---------|---------------| | `financial_advisor` | `no_pii`, disclaimer (not personalized financial advice) | | `legal_info` | `no_pii`, disclaimer (not legal advice) | | `hr_advisor` | `no_pii`, disclaimer (general HR guidance) | | `customer_support_tier1` | `no_pii` | | `sales_assistant` | `no_pii` | Personas in the `technical`, `creative`, `data`, and `education` categories have no default guards, since their domains rarely involve sensitive personal data or liability concerns. You can always add more guards on top of the defaults: ```{python} #| eval: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("financial_advisor") # Gets no_pii + disclaimer .guardrail(tb.tone_check("professional")) # Add your own on top .guardrail(tb.max_response_length(500)) ) ``` To skip the persona's default guards entirely, pass `default_guards=False`: ```{python} #| eval: false import talk_box as tb # Load the persona's prompt and config, but not its guards bot = tb.ChatBot().persona_pack("financial_advisor", default_guards=False) ``` This is useful when you need full control over the guard stack, or when testing the persona's raw behavior without guardrail intervention. ## Writing Custom Guards The built-in guards cover common scenarios, but every application has domain-specific rules. Any function that takes a `str` and returns a `GuardResult` can become a guard using the `@tb.guardrail` decorator. ### Basic Custom Guard Here's a guard that prevents the chatbot from mentioning competitor names, which is a common requirement for customer-facing bots: ```{python} import talk_box as tb @tb.guardrail def no_competitor_mentions(text: str) -> tb.GuardResult: """Block or redact mentions of competitor names.""" competitors = ["acme corp", "globex", "initech"] text_lower = text.lower() for name in competitors: if name in text_lower: return tb.GuardResult.blocked(f"Competitor mention detected: {name}") return tb.GuardResult.passed() # Test it result = no_competitor_mentions.check("How does this compare to Acme Corp?") print(f"Action: {result.action.value}") print(f"Reason: {result.reason}") ``` The `@tb.guardrail` decorator converts the function into a `Guard` object with a `.check()` method, a name (derived from the function name), and a default phase of `BOTH`. ### Guard with Rewriting Sometimes you don't want to block and you instead want to silently fix the output. This guard strips external URLs from responses, useful for chatbots that shouldn't direct users away from your platform: ```{python} import re import talk_box as tb @tb.guardrail(name="URL Redactor", phase=tb.GuardPhase.OUTPUT) def redact_urls(text: str) -> tb.GuardResult: """Replace URLs with a placeholder to prevent link sharing.""" cleaned = re.sub(r"https?://\S+", "[URL removed]", text) if cleaned != text: return tb.GuardResult.rewrite(cleaned, reason="Removed external URLs") return tb.GuardResult.passed() result = redact_urls.check("Check out https://example.com/secret-page for details") print(f"Action: {result.action.value}") print(f"Result: {result.message}") ``` Notice the decorator accepts keyword arguments: `name` overrides the display name used in telemetry, and `phase` restricts when the guard runs. ### Using Custom Guards with ChatBot Custom guards integrate identically to built-in ones. Here, a `require_greeting` guard ensures every response starts with a friendly greeting (rewriting the output if the model forgot): ```{python} #| eval: false import talk_box as tb @tb.guardrail def require_greeting(text: str) -> tb.GuardResult: """Ensure bot responses start with a greeting.""" greetings = ["hello", "hi", "hey", "greetings", "welcome"] if any(text.lower().startswith(g) for g in greetings): return tb.GuardResult.passed() return tb.GuardResult.rewrite(f"Hello! {text}", reason="Added greeting") bot = tb.ChatBot().guardrail(require_greeting) convo = bot.chat("What is the meaning of life?") print(convo.get_last_message().content) ``` ```{python} #| echo: false import talk_box as tb @tb.guardrail def require_greeting(text: str) -> tb.GuardResult: greetings = ["hello", "hi", "hey", "greetings", "welcome"] if any(text.lower().startswith(g) for g in greetings): return tb.GuardResult.passed() return tb.GuardResult.rewrite(f"Hello! {text}", reason="Added greeting") bot = ( tb.ChatBot() .guardrail(require_greeting) .mock_responses(["The answer to your question is 42."]) ) convo = bot.chat("What is the meaning of life?") print(convo.get_last_message().content) ``` The model's response didn't start with a greeting, so the guard prepended "Hello!" automatically. The user sees a polished interaction without knowing the guard intervened. ## Monitoring Guard Activity In production, you need visibility into how often each guard fires. Are your PII guards catching real data, or are they idle? Is the tone check blocking too aggressively (a sign of false positives)? The `guard_stats()` method provides per-guard activation counts: ```{python} #| eval: false import talk_box as tb bot = ( tb.ChatBot() .guardrail(tb.no_pii()) .guardrail(tb.max_response_length(200)) ) # Chat with the bot for a while... bot.chat("What's my balance?") bot.chat("How do I reset my password?") bot.chat("What's the support email?") # Check guard activity stats = bot.guard_stats() for guard_name, counts in stats.items(): print(f"{guard_name}: {counts}") ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .guardrail(tb.no_pii()) .guardrail(tb.max_response_length(200)) .mock_responses([ "Your account balance is $1,234.56.", "I can help with that! Here's a detailed explanation of the process.", "Contact support at help@example.com for further assistance.", ]) ) bot.chat("What's my balance?") bot.chat("How do I reset my password?") bot.chat("What's the support email?") stats = bot.guard_stats() for guard_name, counts in stats.items(): print(f"{guard_name}: {counts}") ``` Each guard tracks three counters: `passed` (text was fine), `blocked` (text was rejected), and `rewritten` (text was modified). Use these numbers to tune your guard configuration. A guard that never fires may be unnecessary, while one that blocks frequently may need its sensitivity adjusted. ## Real-World Patterns The following examples show how to compose multiple guards into cohesive protection layers for production use cases. ### Financial Advisor with Full Protection A financial chatbot needs layered defenses: no PII leakage, no specific stock recommendations (liability risk), professional tone, and a legal disclaimer on every response. Here's how that looks with Talk Box: ```{python} #| eval: false import talk_box as tb @tb.guardrail(name="No Specific Tickers") def no_stock_picks(text: str) -> tb.GuardResult: """Prevent the bot from recommending specific stocks.""" import re # Match common ticker patterns like $AAPL or (TSLA) tickers = re.findall(r"(?:\$[A-Z]{1,5}|\([A-Z]{1,5}\))", text) if tickers: return tb.GuardResult.blocked( f"Cannot recommend specific securities: {', '.join(tickers)}" ) return tb.GuardResult.passed() bot = ( tb.ChatBot() .persona_pack("financial_advisor") .guardrail(tb.no_pii()) .guardrail(no_stock_picks) .guardrail(tb.tone_check("professional")) .guardrail(tb.disclaimer_required( "\n\n---\n*This is educational content only, not financial advice. " "Consult a licensed financial advisor for personalized guidance.*" )) ) convo = bot.chat("How should I invest for retirement?") print(convo.get_last_message().content) ``` ```{python} #| echo: false import talk_box as tb @tb.guardrail(name="No Specific Tickers") def no_stock_picks(text: str) -> tb.GuardResult: import re tickers = re.findall(r"(?:\$[A-Z]{1,5}|\([A-Z]{1,5}\))", text) if tickers: return tb.GuardResult.blocked( f"Cannot recommend specific securities: {', '.join(tickers)}" ) return tb.GuardResult.passed() bot = ( tb.ChatBot() .persona_pack("financial_advisor") .guardrail(tb.no_pii()) .guardrail(no_stock_picks) .guardrail(tb.tone_check("professional")) .guardrail(tb.disclaimer_required( "\n\n---\n*This is educational content only, not financial advice. " "Consult a licensed financial advisor for personalized guidance.*" )) .mock_responses([ "For retirement planning, consider a diversified approach: allocate across " "broad market index funds, bonds, and international equities based on your " "risk tolerance and time horizon. A common starting framework is the " "'age in bonds' rule: subtract your age from 110 to get your stock allocation." ]) ) convo = bot.chat("How should I invest for retirement?") print(convo.get_last_message().content) ``` The custom `no_stock_picks` guard demonstrates how domain-specific rules integrate naturally alongside the built-in guards. The response passes through all four layers: PII cleaned, no tickers found, tone verified professional, and disclaimer appended. ### Customer Support with Input Validation Customer support bots face a different threat model: abusive inputs, prompt-stuffing attacks, and legal escalation triggers. This configuration blocks legal threats at the input stage (before the LLM even processes them), while still protecting output with PII stripping: ```{python} #| eval: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("customer_support_tier1") .guardrail(tb.no_pii()) .guardrail(tb.max_input_length(2000)) .guardrail(tb.keyword_block( ["lawsuit", "lawyer", "attorney"], phase=tb.GuardPhase.INPUT )) ) # Normal message works fine convo = bot.chat("I need help with my order #12345") print(f"Normal: {convo.get_last_message().content}") # Legal threat is blocked convo = bot.chat("I'm calling my lawyer about this") print(f"Legal: {convo.get_last_message().content}") ``` ```{python} #| echo: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("customer_support_tier1") .guardrail(tb.no_pii()) .guardrail(tb.max_input_length(2000)) .guardrail(tb.keyword_block( ["lawsuit", "lawyer", "attorney"], phase=tb.GuardPhase.INPUT )) .mock_responses(["I'll look into that for you."]) ) convo = bot.chat("I need help with my order #12345") print(f"Normal: {convo.get_last_message().content}") convo = bot.chat("I'm calling my lawyer about this") print(f"Legal: {convo.get_last_message().content}") ``` The legal keyword guard fires on the input phase, so the LLM never sees the threatening message. This protects against both wasted tokens and the risk of the model responding inappropriately to legal threats. ## Guard Composition Best Practices Guard ordering affects behavior. Because each guard passes its output to the next, place them in this sequence: 1. **Input validation**: reject bad inputs early (`max_input_length`, `keyword_block`) 2. **PII protection**: strip sensitive data before processing (`no_pii`) 3. **Output quality**: enforce standards on responses (`tone_check`, `must_cite_sources`) 4. **Output formatting**: final adjustments (`max_response_length`, `disclaimer_required`) This layering ensures that expensive checks (like tone analysis) only run on text that already passed cheaper checks (like length limits), and that formatting guards like `disclaimer_required` append text *after* truncation rather than before it. Every guard is independent and testable in isolation. Call `.check(text)` on any guard before attaching it to a chatbot to verify it behaves as expected. The same guard instance can be reused across multiple chatbots, and built-in guards mix freely with custom ones in any order. Once deployed, use `.guard_stats()` to monitor activation rates and tune sensitivity. A guard that never fires may be unnecessary, while one that blocks on every message likely needs its threshold adjusted. ### Installation Get Talk Box up and running in your Python environment with these simple installation steps. ## Requirements - **Python 3.11 or higher** - **pip** or **conda** package manager ## Basic Installation ### Option 1: Install from PyPI (Recommended) ```bash pip install talk-box ``` ### Option 2: Development Installation For the latest features or to contribute to development: ```bash git clone https://github.com/rich-iannone/talk-box.git cd talk-box pip install -e . ``` ## AI Provider Setup Talk Box integrates with multiple AI providers. You'll need to set up at least one provider to use real AI models. ::: {.callout-tip} ## Using a `.env` file (Recommended) For security and convenience, you can store all your API keys in a `.env` file in your project directory: 1. Create a file named `.env` in your project root 2. Add your API keys (one per line): ``` OPENAI_API_KEY=your-openai-key-here ANTHROPIC_API_KEY=your-anthropic-key-here GOOGLE_API_KEY=your-google-key-here ``` 3. Install python-dotenv: `pip install python-dotenv` 4. Load in Python: ```python from dotenv import load_dotenv load_dotenv() # Loads variables from .env file ``` **Important:** Add `.env` to your `.gitignore` file to avoid committing API keys to version control! ::: ### OpenAI (Recommended for beginners) 1. **Get an API key** from [OpenAI](https://platform.openai.com/api-keys) 2. **Set your API key** (choose one method): **Environment Variable:** ```bash export OPENAI_API_KEY="your-api-key-here" ``` **In Python:** ```python import os os.environ["OPENAI_API_KEY"] = "your-api-key-here" ``` ### Anthropic (Claude) 1. **Get an API key** from [Anthropic](https://console.anthropic.com/) 2. **Set your API key:** ```bash export ANTHROPIC_API_KEY="your-api-key-here" ``` ### Google (Gemini) 1. **Get an API key** from [Google AI Studio](https://makersuite.google.com/app/apikey) 2. **Set your API key:** ```bash export GOOGLE_API_KEY="your-api-key-here" ``` ## Verify Installation Test your installation with this simple script: ```python import talk_box as tb # Check if Talk Box is working bot = tb.ChatBot() print("✅ Talk Box installed successfully!") # Check AI integration (requires API key) try: response = bot.chat("Say hello!") print("LLM integration working!") print(f"Response: {response.get_last_message().content}") except Exception as e: print("LLM integration needs setup:") print(f" {e}") print(" See the AI Provider Setup section above") ``` ## Installation Troubleshooting ### Common Issues **"ModuleNotFoundError: No module named 'talk_box'"** - Make sure you installed with the correct Python environment - Try: `python -m pip install talk-box` **"API key not found" errors** - Verify your API key is set correctly - Check the environment variable name matches your provider - Restart your Python session after setting environment variables **Permission errors on installation** - Try: `pip install --user talk-box` - Or use a virtual environment (recommended) ## Optional Dependencies **Development tools:** ```bash pip install talk-box[dev] ``` **All optional dependencies:** ```bash pip install talk-box[all] ``` ### Model Selection Selecting the appropriate AI model is crucial for achieving optimal performance, cost-effectiveness, and user experience in your Talk Box applications. This guide covers the key considerations and trade-offs for different model types and providers. ## Model Overview Talk Box supports any model available through its `chatlas` backend, which covers 11 LLM providers. Here are the most commonly used models organized by capability tier: ### Frontier Models (Best Reasoning) These models excel at complex tasks requiring deep analysis, nuanced understanding, and sophisticated outputs: ```python import talk_box as tb # OpenAI bot = tb.ChatBot().model("gpt-4o") # Anthropic bot = tb.ChatBot().model("claude-sonnet-4-6") # Google bot = tb.ChatBot().model("gemini-pro") ``` ### Fast & Efficient Models (Best Value) These models offer excellent performance for straightforward tasks at lower cost and latency: ```python import talk_box as tb # OpenAI bot = tb.ChatBot().model("gpt-4o-mini") # Anthropic bot = tb.ChatBot().model("claude-haiku-3.5-20241022") # Google bot = tb.ChatBot().model("gemini-flash") ``` ### Model Characteristics | Model | Reasoning | Speed | Cost | Context | Best For | |-------|-----------|-------|------|---------|----------| | **GPT-4o** | Excellent | Fast | Medium | 128K | General-purpose, multimodal, production apps | | **GPT-4o-mini** | Good | Very Fast | Low | 128K | High-volume tasks, simple interactions | | **Claude Sonnet 4** | Excellent | Medium | Medium | 200K | Long documents, detailed analysis, coding | | **Claude Haiku 3.5** | Good | Very Fast | Very Low | 200K | High-volume, cost-sensitive workloads | | **Gemini Pro** | Very Good | Medium | Medium | 1M | Multimodal, very long context | | **Gemini Flash** | Good | Very Fast | Low | 1M | Fast multimodal processing | ## Practical Provider Selection ### Choosing a Provider Each provider has different strengths. Here's a practical decision framework: **Choose OpenAI (GPT-4o)** when you need: - Excellent all-around performance - Strong multimodal capabilities (vision, audio) - Widest ecosystem support and tooling ```python # Production chatbot with good balance bot = ( tb.ChatBot() .model("gpt-4o") .temperature(0.7) .max_tokens(1500) ) ``` **Choose Anthropic (Claude Sonnet 4)** when you need: - Long document analysis (200K context) - Careful, nuanced responses - Strong coding and analytical tasks ```python # Document analysis with large context bot = ( tb.ChatBot() .model("claude-sonnet-4-6") .temperature(0.4) .max_tokens(4000) ) ``` **Choose Google (Gemini)** when you need: - Very long context (up to 1M tokens) - Fast, cost-effective multimodal processing - Integration with Google ecosystem ```python # Long-context analysis bot = ( tb.ChatBot() .model("gemini-pro") .temperature(0.5) .max_tokens(2000) ) ``` ### Using Provider-Prefixed Model Strings For explicit provider selection, use the `provider_model()` method: ```python # Explicit provider specification bot = tb.ChatBot().provider_model("openai:gpt-4o") bot = tb.ChatBot().provider_model("anthropic:claude-sonnet-4-6") bot = tb.ChatBot().provider_model("google:gemini-pro") ``` ### Task-Specific Recommendations Different tasks benefit from different model strengths: ```python import talk_box as tb # Code review: needs strong reasoning code_bot = ( tb.ChatBot() .model("gpt-4o") .preset("technical_advisor") .temperature(0.2) ) # Creative writing: benefits from Claude's nuance writer_bot = ( tb.ChatBot() .model("claude-sonnet-4-6") .preset("creative_writer") .temperature(0.8) ) # Customer support: fast responses, lower cost support_bot = ( tb.ChatBot() .model("gpt-4o-mini") .preset("customer_support") .temperature(0.4) ) # Data analysis: structured thinking analyst_bot = ( tb.ChatBot() .model("gpt-4o") .preset("data_analyst") .temperature(0.3) ) ``` ### Temperature Guidelines Temperature controls randomness in responses. Match it to your use case: | Temperature | Use Case | Example | |-------------|----------|---------| | 0.0–0.3 | Factual, analytical, code review | Technical advisory | | 0.4–0.6 | Balanced, conversational | Customer support | | 0.7–0.9 | Creative, varied responses | Creative writing | | 1.0+ | Maximum variety (use cautiously) | Brainstorming | ## Local Models with Ollama Talk Box supports local models through Ollama, giving you privacy, zero API costs, and offline capability. ### Setting Up Ollama 1. Install Ollama from [ollama.ai](https://ollama.ai) 2. Pull a model: ```bash ollama pull llama3.1 ollama pull mistral ollama pull codellama ``` 3. Use with Talk Box: ```python import talk_box as tb # Use a local Ollama model bot = tb.ChatBot().provider_model("ollama:llama3.1") # Or with specific configuration bot = ( tb.ChatBot() .provider_model("ollama:mistral") .temperature(0.7) .max_tokens(2000) ) response = bot.chat("Explain Python decorators") ``` ### When to Use Local Models Local models are ideal when: - **Privacy is critical**: data never leaves your machine - **No internet required**: works completely offline - **Zero marginal cost**: no per-token API charges - **Development/testing**: iterate quickly without API rate limits Trade-offs to consider: - Generally lower capability than frontier cloud models - Require local GPU for good performance - Model sizes limited by your hardware RAM/VRAM ### Recommended Local Models | Model | Size | Best For | |-------|------|----------| | `llama3.1` | 8B–70B | General purpose, good reasoning | | `mistral` | 7B | Fast, good for conversational tasks | | `codellama` | 7B–34B | Code generation and analysis | | `phi3` | 3.8B | Lightweight, runs on CPU | ### Combining Local and Cloud Models A common pattern is using local models for development and cloud models for production: ```python import os import talk_box as tb def create_bot(use_local: bool = False): """Create a bot with local or cloud model based on environment.""" if use_local or os.getenv("USE_LOCAL_MODEL"): return tb.ChatBot().provider_model("ollama:llama3.1") else: return tb.ChatBot().model("gpt-4o") # Development bot = create_bot(use_local=True) # Production bot = create_bot(use_local=False) ``` ## Best Practices ### 1. Start with GPT-4o or Claude Sonnet 4 Begin with a frontier model to validate your application logic, then optimize for cost/speed: ```python # Start here for development bot = tb.ChatBot().model("gpt-4o").temperature(0.7) ``` ### 2. Match Model to Task Complexity Don't use frontier models for simple tasks: ```python # Simple classification or routing → fast model router = tb.ChatBot().model("gpt-4o-mini").temperature(0.1) # Complex multi-step analysis → frontier model analyst = tb.ChatBot().model("gpt-4o").temperature(0.3) ``` ### 3. Implement Fallbacks Always have a backup model for reliability: ```python def chat_with_fallback(message: str, primary="gpt-4o", fallback="gpt-4o-mini"): """Chat with automatic fallback on failure.""" try: bot = tb.ChatBot().model(primary) return bot.chat(message) except Exception: bot = tb.ChatBot().model(fallback) return bot.chat(message) ``` ### 4. Use Lower Temperature for Consistency Production applications benefit from lower temperature for predictable behavior: ```python # Production: consistent, reliable responses production_bot = tb.ChatBot().model("gpt-4o").temperature(0.3) # Experimentation: varied, creative responses creative_bot = tb.ChatBot().model("gpt-4o").temperature(0.9) ``` ## Managing Context Windows When switching between models with different context sizes (e.g., Claude's 200K vs. a local 8K model), you need to ensure your prompts and conversation history fit. The `ContextWindow` class handles this automatically: ```python import talk_box as tb # Create a context window from a model profile ctx = tb.ContextWindow(model="ollama:llama3.2:latest") # Or with an explicit token budget ctx = tb.ContextWindow(max_tokens=8192, reserve_output=2048) ``` ### Fitting Conversation Messages `fit_messages()` trims conversation history to fit, dropping older messages first: ```python messages = [ {"role": "user", "content": "Hello!"}, {"role": "assistant", "content": "Hi! How can I help?"}, {"role": "user", "content": "Explain Python decorators in detail..."}, # ... many more turns ] ctx = tb.ContextWindow(max_tokens=4096, reserve_output=1024) result = ctx.fit_messages(messages, system_prompt="You are a helpful tutor.") print(f"Kept {len(result.messages)} of {len(messages)} messages") print(f"Using {result.tokens_used}/{result.token_budget} input tokens") print(f"Dropped {result.messages_dropped} oldest messages") ``` Two strategies are available: - **`truncate_oldest`** (default): drops the oldest messages first, preserving recent context - **`truncate_middle`**: keeps the first message (sets context) and the most recent messages, dropping from the middle ```python # Keep the opening message and recent exchanges result = ctx.fit_messages(messages, strategy="truncate_middle") ``` ### Fitting Prompts For `PromptBuilder` prompts that are too large for a model, `fit_prompt()` drops lowest-priority sections: ```python builder = ( tb.PromptBuilder() .persona("data analyst", "statistics") .task_context("Analyze quarterly sales data") .structured_section("BACKGROUND", long_context, priority=tb.Priority.LOW) .structured_section("KEY METRICS", metrics, priority=tb.Priority.CRITICAL) .constraint("Be concise") ) ctx = tb.ContextWindow(model="ollama:llama3.2:latest") result = ctx.fit_prompt(builder) if result.sections_dropped: print(f"Dropped {len(result.sections_dropped)} low-priority sections to fit") ``` ### Quick Budget Checks Use `fits()` and `overflow()` for simple checks without fitting: ```python ctx = tb.ContextWindow(model="openai:gpt-4o") prompt = str(my_builder) if ctx.fits(prompt): print("Prompt fits within budget") else: print(f"{ctx.overflow(prompt)} tokens over budget") ``` ## Key Takeaways - **GPT-4o** and **Claude Sonnet 4** are excellent defaults for most applications - **GPT-4o-mini** and **Claude Haiku 3.5** are best for high-volume, cost-sensitive workloads - **Ollama** provides local, private, zero-cost inference for development and privacy-sensitive use cases - Match temperature to your task: low for analytical, higher for creative - Always implement fallback strategies for production reliability ### Conversational Pathways Pathways provide intelligent conversation flow guidance while maintaining the flexibility to adapt to natural conversation patterns. Think of them as guardrails rather than rigid state machines. They help LLMs provide consistent and thorough assistance while remaining responsive to user needs. ## What Are Pathways? A Pathway defines a structured flow through a conversation, breaking complex interactions into clear states with specific objectives. Each state represents a step in achieving the overall goal, with defined information requirements, success conditions, and transition logic. Some of the key benefits of Pathways are: - **Consistency**: ensure important steps aren't skipped - **Thoroughness**: gather all necessary information systematically - **Flexibility**: adapt to natural conversation patterns - **Error Recovery**: handle unexpected situations gracefully - **Scalability**: manage complex multi-step processes ## Basic Pathway Structure Every pathway follows this pattern: ```{python} import talk_box as tb pathway = ( tb.Pathways( title="Process Name", desc="clear description of what this pathway accomplishes", activation="when to use this pathway", completion_criteria="what indicates success", fallback_strategy="how to handle edge cases" ) # === STATE: state_name === .state("state name: description of what happens") .required(["essential information needed"]) .optional(["helpful but not required info"]) .success_condition("How to know this state is complete") .next_state("next_state_name") # ...include more states ) ``` ## Creating Your First Pathway Let's build a customer onboarding pathway step by step: ```{python} # Start with pathway setup onboarding = ( tb.Pathways( title="Customer Onboarding", desc="welcome new customers and set up their accounts", activation="new customer signs up", completion_criteria="customer is ready to use the platform", fallback_strategy="if customer needs help, provide direct support contact" ) # === STATE: welcome === .state("welcome: welcome customer and collect basic information") .required([ "customer's full name", "email address", "company or organization name" ]) .success_condition("customer feels welcomed and basic info is collected") .next_state("setup") # === STATE: setup === .state("setup: configure account preferences") .required([ "password created and confirmed", "notification preferences selected", "timezone configured" ]) .optional(["profile photo uploaded", "team member invitations"]) .success_condition("Account is fully configured") .next_state("tour") # === STATE: tour === .state("tour: provide guided tour of key features") .required(["main features demonstrated", "first task completed"]) .success_condition("customer understands how to use core functionality") ) ``` A flow diagram of the `Pathways` object can be viewed in HTML notebooks: ```{python} onboarding ``` And we can view the pathway structure as a formatted prompt fragment via `print()`: ```{python} print(onboarding) ``` This example demonstrates how pathways create structured yet flexible conversation flows. Notice how each state builds logically on the previous one—we collect basic information first, then configure account preferences, and finally provide training. This progressive approach helps users feel guided through what could otherwise be an overwhelming process. The pathway uses clear, specific requirements at each step (like `"password created and confirmed"` rather than just `"password"`), which helps the AI understand exactly what to accomplish. Optional items in the setup state show how pathways can accommodate different user needs while maintaining the core flow structure. ## State Types and Inference Pathways automatically infer both state types and IDs based on the methods you use and the shorthand syntax: - **State Types**: Inferred from method usage (`.required()` → `"collect"`, `.branch_on()` → `"decision"`, `.tools()` → `"tool"`) - **State IDs**: Extracted from `"id: description"` format, with automatic normalization (spaces → underscores) - **State Blocks**: Method calls between `.state()` definitions belong to the previous state, creating natural configuration blocks ### Collection States (`type="collect"`) Automatically inferred when using `.required()` or `.optional()`: ```python .state("requirements: gather project requirements") .required(["project goals", "timeline", "budget range"]) .optional(["preferred technologies", "team size"]) ``` Collection states are ideal for systematic information gathering. When you specify what information is required or optional, the AI knows to ask questions and collect responses before moving forward. ### Decision States (`type="decision"`) Automatically inferred when using `.branch_on()`: ```python .state("triage: determine support type needed") .branch_on("technical issue reported", id="tech_support") .branch_on("billing question asked", id="billing") .branch_on("general inquiry", id="general_help") ``` Decision states create conditional pathways based on user responses or circumstances. The AI evaluates which branch condition matches the situation and routes the conversation accordingly. ### Tool States (`type="tool"`) Automatically inferred when using `.tools()`: ```python .state("diagnostics: analyze system performance") .tools(["system_monitor", "log_analyzer", "performance_profiler"]) .success_condition("performance issues identified") ``` Tool states enable external capabilities and automated processes. When you specify tools, the AI understands it needs to use those resources to accomplish the state's objectives. ### Chat States (`type="chat"`) The default for open conversation, explanations, and guidance: ```python .state("explanation: explain the recommended solution") .success_condition("customer understands the approach") ``` Chat states handle open-ended conversation, explanations, and guidance where no specific tools or branching logic are needed. This is the default state type when you don't use collection, decision, or tool methods. ## Branching and Decision Logic Use `.branch_on()` to create conditional flows: ```{python} support_pathway = ( tb.Pathways( title="Customer Support Triage", desc="route customers to appropriate support channels", activation="customer needs assistance" ) # === STATE: assessment === .state("assessment: assess customer needs") .required(["issue description", "urgency level", "customer type"]) .next_state("triage") # === STATE: triage === .state("triage: route to appropriate support") # Perform branching ----- .branch_on("critical system outage", id="emergency") .branch_on("technical issue needing expert help", id="technical") .branch_on("billing or account question", id="billing") .branch_on("general question or guidance needed", id="general") # === STATE: emergency === .state("emergency: handle critical emergency") .required(["incident escalated", "immediate response initiated"]) .success_condition("emergency team engaged") .next_state("follow_up") # === STATE: technical === .state("technical: provide technical support") .tools(["diagnostic_tools", "knowledge_base", "screen_sharing"]) .success_condition("technical issue resolved or escalated appropriately") .next_state("follow_up") # === STATE: follow_up === .state("follow up: ensure customer satisfaction") .required(["resolution confirmed", "satisfaction rating collected"]) .success_condition("customer issue fully resolved") ) support_pathway ``` Branching logic enables pathways to handle diverse user scenarios while maintaining a structured approach. By defining conditions for each branch, you can create intelligent routing that adapts conversations to specific user needs while also ensuring consistent outcomes. ## Error Handling with Fallbacks Use `.fallback()` to handle situations where normal flow doesn't work: ```{python} import talk_box as tb problem_solving_pathway = ( tb.Pathways( title="Technical Problem Resolution", desc="systematically resolve technical issues", activation="user reports technical problem" ) # === STATE: analysis === .state("analysis: analyze the reported problem") .required(["problem details", "error messages", "system context"]) .success_condition("problem is clearly understood") .next_state("standard_solution") # === STATE: standard_solution === .state("standard solution: apply standard troubleshooting steps") .required(["troubleshooting steps completed", "results documented"]) .success_condition("problem is resolved") .fallback("standard solution doesn't work", "advanced_diagnostics") .next_state("completion") # Normal success path # === STATE: advanced_diagnostics === .state("advanced diagnostics: perform detailed system analysis") .tools(["system_diagnostics", "log_analyzer", "network_tracer"]) .success_condition("root cause identified and resolved") .fallback("issue remains unresolved", "escalation") .next_state("completion") # Success after advanced diagnostics # === STATE: escalation === .state("escalation: escalate to specialist support") .required(["detailed case summary", "specialist contacted"]) .success_condition("case transferred successfully") .next_state("completion") # All paths converge here # === STATE: completion === .state("completion: document resolution and close case") .required(["resolution documented", "customer notified"]) .success_condition("case fully resolved and documented") ) problem_solving_pathway ``` This fallback pattern is essential for creating robust pathways that gracefully handle real-world complexity. By defining clear escalation paths, you ensure that conversations never reach dead ends, maintaining user confidence even when standard approaches fail. ## Using Pathways with `ChatBot` Once you've designed a pathway, you'll want to integrate it with a `ChatBot` to enable structured conversations in practice. Pathways work seamlessly with the `ChatBot` class through the `PromptBuilder` system, automatically providing the AI model with clear guidance about conversation flow, state transitions, and information requirements. ```{python} # Create your pathway support_pathway = ( tb.Pathways( title="Customer Support", desc="comprehensive customer assistance", activation="Customer needs help", ) # === STATE: intake === .state("intake: understand customer needs") .required(["problem description", "contact information"]) .next_state("resolution") # === STATE: resolution === .state("resolution: provide solution") .success_condition("customer problem is resolved") ) # Use with ChatBot via PromptBuilder bot = ( tb.ChatBot() .model("gpt-4") .system_prompt( tb.PromptBuilder() .persona("helpful customer support agent") .pathways(support_pathway) ) ) bot ``` Now configured with the Pathways directives, the bot will now follow the structure you defined. ```python response = bot.chat("I'm having trouble with my account") ``` ## Best Practices ### 1. Clear State Descriptions ```python # Good: Specific and actionable .state("shipping: collect shipping address and delivery preferences") # Avoid: Vague or unclear .state("info: get info") ``` Clear, descriptive state names help both AI models and human developers understand the purpose and scope of each step. When state descriptions are specific, the AI can better guide conversations toward the intended outcomes and provide appropriate responses to user questions. ### 2. Specific Information Requirements ```python # Good: Concrete and measurable .required([ "complete shipping address with postal code", "preferred delivery time window", "special delivery instructions if any" ]) # Avoid: Generic or ambiguous .required(["address", "preferences"]) ``` Detailed requirement specifications ensure the AI knows exactly what information to gather and how to validate completeness. This reduces back-and-forth exchanges and helps users provide the right level of detail from the start. ### 3. Observable Success Conditions ```python # Good: Clear completion criteria .success_condition("customer confirms shipping details are correct") # Avoid: Internal or unclear .success_condition("data is valid") ``` Success conditions should describe observable user behaviors or confirmations rather than internal system states. This helps the AI recognize when to move forward and gives users clear expectations about what constitutes completion. ### 4. Meaningful State Names ```python # Good: Descriptive and unique .state("order confirmation: review order details and confirm purchase") # Avoid: Generic or confusing .state("process: process order") ``` State IDs serve as navigation waypoints and debugging references throughout your pathway logic. Descriptive names make it easier to understand pathway flow, troubleshoot issues, and maintain complex conversation structures over time. ### 5. Logical Information Flow ```python # Good: Progressive information gathering # === STATE: contact === .state("contact: collect basic contact info") .required(["name", "email"]) .next_state("detailed_requirements") # === STATE: detailed_requirements === .state("detailed requirements: gather detailed project requirements") .required(["project scope", "timeline", "budget"]) ``` Structure your pathway states to build naturally from simple to complex information gathering. This progressive approach feels more conversational and prevents users from feeling overwhelmed by too many questions at once. ## Advanced Patterns Once you're comfortable with basic pathway construction, these advanced patterns help you handle more sophisticated conversation flows. These techniques are particularly useful for complex business processes, multi-step workflows, and scenarios where different user paths need to converge or diverge based on specific conditions. ### Multi-Path Convergence Different branches can reconverge to common states: ```{python} import talk_box as tb multi_branch_pathway = ( tb.Pathways(title="Multi-path Process", desc="...") .state("assessment: initial assessment") .branch_on("path A condition", id="path_a") .branch_on("path B condition", id="path_b") # === STATE: path_a === .state("path a: handle path A") .required(["path A requirements"]) .next_state("completion") # Converge here # === STATE: path_b === .state("path b: handle path B") .required(["path B requirements"]) .next_state("completion") # Converge here # === STATE: completion === .state("completion: complete process") .success_condition("all paths lead to successful completion") ) multi_branch_pathway ``` This pattern demonstrates how different conversation branches can merge back into a common endpoint. The power of convergence lies in its ability to handle diverse user needs or circumstances while ensuring all paths lead to the same comprehensive completion state. For example, a customer service pathway might branch into technical support, billing assistance, or general inquiries, but all branches eventually converge at a customer satisfaction check and case closure state. This approach maintains consistency in final outcomes while allowing flexibility in the journey to get there. ### Progressive Disclosure Progressive disclosure is a design principle that presents information and options incrementally, starting with the most essential elements and gradually revealing more advanced features as users demonstrate readiness or express specific needs. This approach prevents cognitive overload while ensuring power users can access sophisticated capabilities when required. In pathway design, progressive disclosure helps you create conversation flows that feel natural and approachable to beginners while providing depth for experienced users. Instead of overwhelming users with all possible options upfront, you guide them through a logical progression from basic to advanced configurations. ```python complex_pathway = ( tb.Pathways( title="System Configuration", desc="Progressive disclosure pathway" ) .state("basic: basic setup") .required(["essential settings configured"]) .next_state("intermediate") # === STATE: intemediate === .state("intermediate: intermediate configuration") .required(["advanced options reviewed"]) .optional(["performance tuning preferences"]) .branch_on("user wants advanced setup", id="advanced") .next_state("completion") # Skip advanced if not needed # === STATE: advanced === .state("advanced: advanced configuration") .required(["expert settings configured"]) .next_state("completion") # === STATE: completion === .state("completion: finalize setup") .success_condition("System is fully configured and tested") ) ``` This example demonstrates the progressive disclosure pattern in action: starting with basic setup that everyone needs, moving to intermediate configuration with optional customizations, and only branching to advanced features when users explicitly request them. ## Pathway Visualization For complex pathways, visual flow diagrams can help you understand and validate the conversation structure: ```{python} #| eval: false # Create and open an HTML flowchart visualization complex_pathway.visualize() # Or save to a specific file without opening complex_pathway.visualize( title="System Configuration Flow", filename="pathway_diagram.html", auto_open=False ) ``` The `.visualize()` method creates interactive flowcharts with: - visual flow structure showing states and transitions - color-coded state types for quick identification - reconvergence detection highlighting where paths merge - final state indicators with special styling - undefined state warnings for missing referenced states ::: {.callout-tip} ## Visualization Files Generated HTML visualizations are saved to the `pathway_visualizations/` directory by default, making it easy to share diagrams or archive them for documentation. ::: This is especially useful for: - validating pathway logic before implementation - debugging complex branching and reconvergence scenarios - sharing pathway designs with team members - documenting conversation flows for reference ## Summary Pathways provide a powerful way to structure complex conversations while maintaining natural flexibility. A typical pathway development cycle looks like this: ```python # 1. Build your pathway my_pathway = tb.Pathways(title="My Process", desc="...").state("...") # 2. Check the structure in your notebook my_pathway # HTML display shows overview # 3. Review the prompt format print(my_pathway) # See exactly what the AI will receive # 4. Integrate with ChatBot bot = tb.ChatBot().pathways(my_pathway) ``` Some key takeaways: - start with clear pathway objectives and success criteria - use descriptive state names and specific information requirements - let type inference work for you—it reduces boilerplate - handle edge cases with the `.fallback()` method - inspect pathways with `print()` and use visualization for complex flows - keep states focused and break complex processes into multiple branches if needed With Pathways, you can create sophisticated conversation flows that guide users efficiently while adapting to their natural communication patterns. ### Personas Personas are complete, production-ready assistant configurations bundled into a single YAML pack. Each persona includes an attention-optimized system prompt, recommended models, tools, avoid topics, and test queries — everything needed to deploy a high-quality AI assistant in a few lines of code. ## Quick Start ```{python} #| eval: false import talk_box as tb # Load a persona and start chatting bot = tb.ChatBot().persona_pack("code_reviewer") conversation = bot.chat("Review this function for issues") ``` That single `.persona_pack()` call configures: - A `PromptBuilder`-based system prompt using attention-optimized structure - Temperature and token limits tuned for the task - Avoid topics to keep the assistant on track - Tools appropriate for the role ## Available Personas Talk Box ships with 23 personas across five categories. ### Business | Persona | Description | |---------|-------------| | `customer_support_tier1` | Front-line support agent handling inquiries, troubleshooting, and escalation | | `sales_assistant` | Sales support for product positioning, objection handling, and lead qualification | | `hr_advisor` | HR guidance on policies, benefits, onboarding, and employee relations | | `financial_advisor` | Financial analysis, budgeting guidance, and investment education | | `legal_info` | General legal information with strong disclaimers (not legal advice) | | `meeting_facilitator` | Meeting planning, agenda creation, and follow-up action items | ### Technical | Persona | Description | |---------|-------------| | `code_reviewer` | Thorough code review with security, correctness, and style feedback | | `debugging_assistant` | Systematic debugging through hypothesis testing and log analysis | | `security_analyst` | Security vulnerability assessment and remediation guidance | | `devops_engineer` | Infrastructure, CI/CD, containerization, and deployment guidance | | `api_designer` | RESTful API design, documentation, and best practices | | `technical_writer` | Technical documentation writing and information architecture | ### Data | Persona | Description | |---------|-------------| | `data_analyst` | Data exploration, statistical analysis, and insight communication | | `sql_helper` | SQL query writing, optimization, and database design | | `data_viz_advisor` | Data visualization design, chart selection, and storytelling | | `ml_engineer` | Machine learning pipeline design, model selection, and evaluation | ### Education | Persona | Description | |---------|-------------| | `tutor` | Adaptive tutoring using the Socratic method | | `quiz_master` | Interactive quiz creation and knowledge assessment | | `study_guide_creator` | Structured study materials and learning plans | ### Creative | Persona | Description | |---------|-------------| | `writing_coach` | Writing improvement through feedback on clarity, structure, and voice | | `brainstorming_partner` | Creative ideation, lateral thinking, and concept development | | `content_strategist` | Content planning, audience analysis, and editorial strategy | | `ux_writer` | Microcopy, UI text, error messages, and user-facing content | ## Discovering Personas ```{python} #| eval: false from talk_box.personas import list_personas, persona_categories, get_persona # List all persona names names = list_personas() print(names) # Group by category categories = persona_categories() for cat, names in sorted(categories.items()): print(f"{cat}: {names}") # Inspect a specific persona persona = get_persona("code_reviewer") print(persona.display_name) # "Code Reviewer" print(persona.category) # "technical" print(persona.description) # One-line summary print(persona.recommended_models) # Model suggestions ``` ## Using Personas with ChatBot ### Basic Usage ```{python} #| eval: false import talk_box as tb # The simplest way — persona handles everything bot = tb.ChatBot().persona_pack("customer_support_tier1") ``` ### Overriding Settings You can override any persona setting by chaining additional configuration after `.persona_pack()`: ```{python} #| eval: false import talk_box as tb bot = ( tb.ChatBot() .persona_pack("code_reviewer") .provider_model("ollama:codellama") # Override the model .temperature(0.0) # Override temperature .avoid(["tabs vs spaces debates"]) # Add more avoid topics ) ``` The persona sets defaults; anything you chain after it takes priority. ### Viewing the Generated Prompt Every persona builds its system prompt through `PromptBuilder`, following the attention-optimized structure (persona first, constraints next, analysis in the middle, emphasis at the end): ```{python} #| eval: false import talk_box as tb bot = tb.ChatBot().persona_pack("code_reviewer") bot.show("prompt") ``` ## Persona YAML Structure Each persona is a YAML file in `talk_box/personas/packs/`. Here's the structure: ```yaml name: code_reviewer display_name: "Code Reviewer" category: technical description: "Senior code reviewer providing constructive feedback." # PromptBuilder fields (attention-optimized positions) persona_role: "senior software engineer and code review specialist" expertise: "code quality, design patterns, security vulnerabilities" task_context: > You review code submissions and provide actionable feedback. critical_constraints: - "Never approve code with known security vulnerabilities" - "Always distinguish between must-fix and nice-to-have" constraints: - "Be constructive — explain what's wrong AND how to fix it" - "Prioritize: security > correctness > performance > style" core_analysis: - "Check for security vulnerabilities" - "Evaluate correctness and edge cases" - "Assess readability and maintainability" output_format: - "Organize feedback by severity: Critical, Important, Suggestion" - "Include code examples for suggested changes" final_emphasis: > The goal of code review is to improve code quality while respecting the author. # ChatBot configuration avoid_topics: - "personal criticism of the developer" tools: - "text_stats" recommended_models: - provider_model: "anthropic:claude-sonnet-4-6" context: "Excellent at understanding code context" - provider_model: "openai:gpt-4o" context: "Strong code analysis across many languages" - provider_model: "ollama:codellama" context: "Local code review for sensitive codebases" temperature: 0.1 max_tokens: 1500 tags: - code-review - engineering test_queries: - "Review this Python function for issues" - "Is this SQL query vulnerable to injection?" ``` ## Creating Custom Personas Write a YAML file following the structure above, then load it: ```{python} #| eval: false from talk_box.personas import load_persona # Load from any path persona = load_persona("my_personas/onboarding_specialist.yaml") # Use its system prompt directly import talk_box as tb bot = tb.ChatBot().system_prompt(persona.build_system_prompt()) ``` ### Design Tips - **`persona_role` and `expertise`** go in the primacy position (start of the prompt). Be specific: "senior DevOps engineer" is better than "helpful assistant". - **`critical_constraints`** get the highest-attention placement. Use these for non-negotiable rules (safety, compliance, scope limits). - **`core_analysis`** defines what the persona focuses on. Keep it to 3--6 items. - **`final_emphasis`** goes in the recency position (end of prompt). Use it to reinforce the single most important behavior. - **`test_queries`** should cover the persona's core use cases and at least one edge case. These are used by automated testing to verify the persona works as expected. - **`recommended_models`** should include at least one cloud option and one local option (Ollama) when possible. ## Personas vs. Presets Talk Box has two systems for configuring assistant behavior: | | Presets | Personas | |---|---------|----------| | **What it sets** | Tone, expertise, verbosity | Full system prompt, tools, models, constraints, tests | | **How it's defined** | Python `Preset` dataclass | YAML file with PromptBuilder fields | | **Prompt structure** | Simple text template | Attention-optimized via PromptBuilder | | **Testing** | None built-in | Test queries for automated validation | | **Best for** | Quick tone/style adjustments | Production-ready assistants | Presets are lightweight and good for prototyping. Personas are the recommended approach for any assistant you plan to deploy or share. ### PromptBuilder The `PromptBuilder` class changes the way that LLM system prompts are written. Instead of treating prompts like human instructions, `PromptBuilder` creates structured prompts that work with how AI models actually process information. ## Why `PromptBuilder` Works Better Traditional prompting often fails because it ignores how AI models process information. AI models use attention mechanisms that have distinct patterns: they front-load importance, cluster related concepts, lose focus when information is scattered, and pay special attention to the end of prompts. `PromptBuilder` automatically structures your prompts to leverage these patterns, resulting in consistently better responses. ## Essential `PromptBuilder` Methods Understanding the core methods helps you build more effective prompts. PromptBuilder provides methods that map to different aspects of attention-optimized prompt construction. ### Foundation Methods These methods establish the basic context and identity for your AI assistant. **`persona(role, expertise)`** defines who the AI should be and what expertise it brings: ```python .persona("senior DevOps engineer", "cloud infrastructure and automation") ``` **`task_context(description)`** clearly states what the AI should accomplish: ```python .task_context("design a scalable microservices architecture for high-traffic e-commerce") ``` **`core_analysis(focus_areas)`** specifies the key areas the AI should analyze: ```python .core_analysis([ "scalability and performance under load", "security and data protection", "cost optimization and resource efficiency", "monitoring and observability" ]) ``` These foundation methods work together to establish clear identity, purpose, and scope for the AI analysis. ### Structure and Control Methods These methods help you control how the AI organizes and constrains its analysis. **`critical_constraint(requirement)`** establishes non-negotiable requirements: ```python .critical_constraint("must comply with PCI DSS standards for payment processing") ``` **`output_format(structure)`** organizes how the response should be structured: ```python .output_format([ "**ARCHITECTURE OVERVIEW**: high-level system design", "**PERFORMANCE STRATEGY**: scaling and optimization approach", "**SECURITY IMPLEMENTATION**: protection mechanisms and protocols", "**MONITORING SETUP**: observability and alerting strategy" ]) ``` **`final_emphasis(reminder)`** provides end-of-prompt guidance that leverages recency bias: ```python .final_emphasis("prioritize security and reliability over clever optimizations") ``` These methods ensure the AI maintains focus on what matters most and organizes its output effectively. ### Advanced Control Methods For more sophisticated prompt engineering, these methods provide fine-grained control over AI attention and behavior. **`focus_on(specific_aspects)`** directs attention to particular areas: ```python .focus_on("Identifying single points of failure and performance bottlenecks") ``` **`constraint(requirement, priority)`** adds constraints with priority levels: ```python .constraint("prefer open-source solutions when possible", priority="medium") ``` **`avoid_topics(topics)`** explicitly excludes certain topics or approaches: ```python .avoid_topics(["Deprecated frameworks", "Vendor lock-in solutions"]) ``` **`example(input_example, output_example)`** shows the AI exactly what kind of input/output pattern you want: ```python .example( input_example="design authentication service for e-commerce platform", output_example=""" ## Service: User Authentication **Technology**: FastAPI + Redis + PostgreSQL **Scaling**: Horizontal with load balancer **Security**: JWT tokens with refresh rotation """) ``` These advanced methods help you create highly specialized prompts for complex professional scenarios. ## Complete Example: Building a Professional Prompt Here's a comprehensive example that demonstrates all the PromptBuilder methods working together to create a sophisticated AI assistant: ```{python} import talk_box as tb # Build a comprehensive security architecture consultant security_architect = ( tb.PromptBuilder() # Foundation methods ----- .persona( "senior security architect", "enterprise security design and threat modeling" ) .task_context("design secure architecture for financial services application") .core_analysis([ "threat modeling and attack surface analysis", "security controls and defense in depth", "compliance requirements (PCI DSS, SOX, GDPR)", "performance impact of security measures", ]) # Structure and control methods ----- .critical_constraint("must achieve PCI DSS Level 1 compliance") .output_format([ "**THREAT ANALYSIS**: attack vectors and risk assessment", "**SECURITY ARCHITECTURE**: controls and implementation strategy", "**COMPLIANCE MAPPING**: requirements and evidence documentation", "**PERFORMANCE IMPACT**: security overhead and optimization", ]) .final_emphasis( "security decisions must be justified with threat models and business risk" ) # Advanced methods ----- .focus_on("zero-trust architecture principles and data protection") .constraint("prefer industry-standard solutions over custom implementations") .avoid_topics([ "deprecated cryptographic standards", "unsupported legacy protocols" ]) .example( input_example="review the authentication system for our payment processing API", output_example=""" **THREAT ANALYSIS**: Session hijacking via weak JWT implementation **SECURITY ARCHITECTURE**: Implement JWT with short expiry + refresh tokens **COMPLIANCE MAPPING**: Satisfies PCI DSS 8.2 (multi-factor authentication) **PERFORMANCE IMPACT**: 5ms token validation overhead, minimal impact """, ) ) ``` We can preview the generated prompt by using `print()`: ```{python} print(security_architect) ``` Now let's create the chatbot with `ChatBot`, supplying it with our structured prompt. ```{python} bot = ( tb.ChatBot() .model("gpt-4o") .temperature(0.3) .system_prompt(security_architect) ) ``` Finally, we can use the fully-configured chatbot. ```python # Use the expert assistant response = bot.chat("Design the authentication architecture for our payment processing system") # Print out the content of the last conversation message print(response.get_last_message().content) ``` This example shows how all the `PromptBuilder` methods work together to create a sophisticated AI assistant that provides expert-level analysis with consistent structure and quality. ## Testing and Debugging Prompts Effective prompt engineering requires testing and iteration. `PromptBuilder` provides tools to help you understand and improve your prompts. ### Preview Your Prompt The easiest way to see what your `PromptBuilder` creates is to print it directly: ```{python} builder = ( tb.PromptBuilder() .persona("data scientist", "machine learning and statistics") .core_analysis(["data quality", "model performance", "business impact"]) ) # Preview the generated prompt print(builder) ``` This shows you the complete structured prompt that will be sent to the AI model. You can then use the `builder` object directly as a system prompt since `PromptBuilder` objects can be passed directly to `ChatBot`. ## Why `PromptBuilder` Works Better Traditional prompting often fails because it ignores how AI models process information. AI models use attention mechanisms that have distinct patterns: they front-load importance, cluster related concepts, lose focus when information is scattered, and pay special attention to the end of prompts. `PromptBuilder` automatically structures your prompts to leverage these patterns, resulting in consistently better responses. ### Traditional vs `PromptBuilder` Comparison Here's a real example showing the difference: ```python import talk_box as tb # Traditional approach: often produces generic feedback bot = tb.ChatBot().model("gpt-4o") response = bot.chat(""" Review this Python code for security issues, performance problems, and code quality. Make sure to check for SQL injection, memory leaks, and other issues. Also suggest improvements. """) # PromptBuilder approach: expert-level analysis security_expert = ( tb.PromptBuilder() .persona("senior security engineer", "application security and code review") .task_context("critical security and performance review for production deployment") .core_analysis([ "security vulnerabilities (SQL injection, XSS, authentication flaws)", "performance bottlenecks and memory issues", "code architecture and maintainability", "testing coverage and edge cases" ]) .critical_constraint("Zero tolerance for security vulnerabilities") .output_format([ "**CRITICAL SECURITY ISSUES**: must fix before deployment", "**PERFORMANCE OPTIMIZATIONS**: impact and implementation effort", "**CODE QUALITY IMPROVEMENTS**: maintainability enhancements", "**TESTING RECOMMENDATIONS**: coverage gaps and test cases" ]) .final_emphasis("prioritize security over performance. Flag anything suspicious.") ) bot = tb.ChatBot().model("gpt-4o").system_prompt(security_expert) response = bot.chat("Review this authentication middleware...") ``` The `PromptBuilder` version produces thorough, well-organized analysis that catches subtle issues and provides actionable recommendations because it works with the AI model's attention patterns rather than against them. ## Real-World Professional Examples Here are some professional applications of `PromptBuilder`, demonstrating how structured prompts consistently outperform traditional approaches across different domains. ### Technical Documentation Specialist Creating developer documentation requires balancing completeness with usability. This `PromptBuilder` configuration focuses the AI on practical, actionable documentation: ```{python} docs_expert = ( tb.PromptBuilder() .persona("technical writing specialist", "developer documentation and API guides") .task_context("create documentation that developers actually use and understand") .core_analysis([ "clear, actionable explanations with working examples", "common use cases and integration patterns", "error handling and troubleshooting guides", "performance considerations and best practices" ]) .critical_constraint("every code example must be tested and functional") .output_format([ "**QUICK START**: working example that runs immediately", "**COMPLETE REFERENCE**: all parameters and options explained", "**TROUBLESHOOTING**: common issues and solutions", "**BEST PRACTICES**: performance and security recommendations" ]) .final_emphasis("documentation quality is measured by developer success, not completeness") ) print(docs_expert) ``` This configuration produces documentation that developers actually use because it prioritizes practical examples and common use cases over exhaustive technical details. ### Product Requirements Analyst Product managers need to transform user requests into clear development specifications. This PromptBuilder helps bridge the gap between user needs and technical implementation: ```{python} product_expert = ( tb.PromptBuilder() .persona("senior product manager", "requirements analysis and user experience design") .task_context("transform user requests into clear, actionable development requirements") .core_analysis([ "user needs and pain points behind the request", "technical feasibility and implementation complexity", "business impact and success metrics", "dependencies and integration requirements" ]) .critical_constraint("all requirements must be testable and measurable") .output_format([ "**USER STORIES**: clear acceptance criteria with examples", "**TECHNICAL REQUIREMENTS**: architecture and implementation notes", "**SUCCESS METRICS**: how to measure if this solves the problem", "**RISKS AND DEPENDENCIES**: potential blockers and mitigation plans" ]) .final_emphasis("focus on solving real user problems, not just implementing features") ) print(product_expert) ``` The structured analysis ensures that both user needs and technical constraints are properly considered in the requirements. ### Business Strategy Consultant Strategic analysis requires balancing multiple complex factors while maintaining focus on actionable outcomes. This configuration guides the AI through comprehensive business analysis: ```{python} strategy_expert = ( tb.PromptBuilder() .persona("senior business strategy consultant", "market analysis and strategic planning") .task_context("strategic analysis and recommendations for business growth") .core_analysis([ "market opportunities and competitive landscape", "revenue model optimization and scalability", "operational efficiency and cost structure", "risk assessment and mitigation strategies" ]) .critical_constraint("all recommendations must include financial impact projections") .output_format([ "**STRATEGIC OPPORTUNITIES**: market gaps and growth potential", "**FINANCIAL IMPACT**: revenue projections and cost analysis", "**IMPLEMENTATION ROADMAP**: phased approach with milestones", "**RISK MITIGATION**: potential challenges and contingency plans" ]) .constraint("prefer data-driven insights over opinions") .final_emphasis("focus on actionable strategies that can be implemented within 90 days") ) print(strategy_expert) ``` ## Best Practices for Effective Prompts Following proven patterns helps you create consistently effective prompts that produce high-quality AI responses. ### Create Specific Personas Vague personas produce generic responses, while specific personas with clear expertise produce focused, expert-level analysis: ```python # Generic persona: produces generic advice .persona("developer", "coding") # Specific persona: produces expert analysis .persona("senior Python developer", "API design and database optimization") ``` ### Front-Load Critical Information AI models allocate maximum attention to the beginning of prompts. This primacy bias means that critical context should come first, not buried in the middle or end of instructions. ```python # Poor: Critical context buried prompt = """ Please analyze this code and look at various aspects like performance, security, maintainability, and other factors. By the way, this is for a financial application handling sensitive customer data, so security is really critical and you should focus on that first. """ # Better: Critical context front-loaded financial_reviewer = ( tb.PromptBuilder() .task_context("CRITICAL: financial application handling sensitive customer data") .critical_constraint("security vulnerabilities are the highest priority concern") .core_analysis([ "security vulnerabilities (customer data at risk)", "performance issues", "maintainability concerns" ]) ) ``` When you front-load critical information, the AI maintains focus on what matters most throughout its analysis. ### Use Clear Task Context Task context should be specific enough to guide the AI toward the right type of analysis: ```python # Too generic: unclear what help is needed .task_context("Help with code") # Specific and actionable: clear scope and objective .task_context("Optimize Django API endpoints for 10x traffic increase") ``` ### Structure Output Effectively Well-structured output formats help the AI organize its analysis and make responses more actionable: ```python # Minimal structure: may produce scattered analysis .output_format(["analysis", "recommendations"]) # Clear structure with specific expectations .output_format([ "**CURRENT STATE ANALYSIS**: what's working and what isn't", "**OPTIMIZATION OPPORTUNITIES**: ranked by impact vs effort", "**IMPLEMENTATION PLAN**: step-by-step with timelines" ]) ``` ### Make Final Emphasis Count Final emphasis should provide specific, actionable guidance rather than generic encouragement: ```python # Weak: doesn't provide useful guidance .final_emphasis("do a good job") # Specific: provides concrete direction .final_emphasis("focus on solutions that can be implemented this sprint") ``` AI models pay special attention to the end of prompts. This recency bias makes final emphasis particularly powerful for ensuring your most important guidance influences the analysis. ```python # Without final emphasis: can trail off basic_reviewer = ( tb.PromptBuilder() .persona("security engineer", "application security review") .core_analysis(["security vulnerabilities", "code quality"]) ) # With final emphasis: maintains focus focused_reviewer = ( tb.PromptBuilder() .persona("security engineer", "application security review") .core_analysis(["security vulnerabilities", "code quality"]) .final_emphasis("this handles customer financial data so err on the side of extreme caution for any security concerns.") ) ``` The final emphasis ensures your most important guidance influences the AI's conclusions and recommendations. ### Avoid Information Overload AI attention has limits, similar to human working memory. Too many simultaneous instructions cause attention drift: ```python # Poor: Too many simultaneous concerns overloaded_prompt = ( tb.PromptBuilder() .core_analysis([ "security vulnerabilities", "performance bottlenecks", "code maintainability", "variable naming", "function design", "error handling", "logging practices", "memory usage", "CPU efficiency", "network optimization", "database queries" ]) ) # Better: Chunked into manageable groups focused_prompt = ( tb.PromptBuilder() .structured_section("Security Analysis", [ "authentication and authorization flaws", "input validation and injection attacks", "data exposure and encryption issues" ]) .structured_section("Performance Analysis", [ "algorithm efficiency and complexity", "database query optimization", "memory usage and garbage collection" ]) ) ``` AI attention works best when related instructions are grouped together. Scattered instructions force the model to constantly refocus, leading to inconsistent analysis. ```python # Poor: Scattered instructions prompt = """ Check for SQL injection. Also look at variable names and see if they're clear. Performance might be an issue too. Make sure error handling is good. Are there any security issues with authentication? Use clear headings in your response. """ # Better: Clustered by domain security_expert = ( tb.PromptBuilder() .structured_section("Security Analysis", [ "SQL injection vulnerabilities", "authentication security flaws", "data exposure risks" ]) .structured_section("Code Quality Analysis", [ "variable naming clarity", "error handling robustness", "performance optimization opportunities" ]) .structured_section("Output Requirements", [ "use clear section headings", "prioritize security issues first" ]) ) ``` Clustering allows the AI to maintain focused attention on each domain, resulting in more comprehensive analysis. ### Maintain Clear Priorities Conflicting instructions confuse AI models and produce inconsistent results: ```python # Poor: Conflicting guidance conflicted_prompt = """ Be comprehensive and thorough in your analysis. Keep your response brief and to the point. """ # Better: Clear priorities clear_prompt = ( tb.PromptBuilder() .task_context("comprehensive security analysis with prioritized findings") .core_analysis([ "critical security vulnerabilities (highest priority)", "important performance issues (medium priority)", "code quality improvements (lower priority)" ]) ) ``` Clear priorities help the AI allocate attention appropriately and produce more useful results. ## Next Steps Ready to put `PromptBuilder` to work? Start with the foundation methods and gradually incorporate advanced features as your needs become more sophisticated. For domain-specific applications, explore domain `Vocabulary` for professional terminology management and conversational `Pathways` for intelligent conversation flow guidance. These advanced features build on `PromptBuilder`'s attention-optimized foundation to create even more sophisticated AI assistants. ### Compliance for Avoiding Topics The `autotest_avoid_topics()` function provides comprehensive automated testing for `ChatBot` avoid topics compliance. It generates sophisticated adversarial questions designed to test whether your bot properly refuses to engage with prohibited topics, then automatically evaluates responses for violations. ## Why Test Avoid Topics? When you configure a `ChatBot` to avoid certain topics, you want confidence that it will consistently refuse to engage with those topics, even when: - users ask directly for prohibited information - questions are phrased indirectly or hypothetically - emotional appeals are used to pressure the bot - role-playing scenarios try to bypass restrictions - persistent follow-up questions push for answers Manual testing is time-consuming and inconsistent. The `autotest_avoid_topics()` function automates this process with sophisticated adversarial testing strategies. ## Basic Usage The simplest way to test avoid topics compliance: ```python import talk_box as tb # Create a bot with avoid topics bot = tb.ChatBot().avoid(["medical_advice", "financial_planning"]) # Test compliance results = tb.autotest_avoid_topics(bot, test_intensity="medium") # View results print(f"Compliance rate: {results.summary['success_rate']:.1%}") print(f"Violations found: {results.summary['violation_count']}") ``` ## Test Intensity Levels Control the thoroughness of testing with different intensity levels: ```python # Light testing - quick validation (3 conversations) results = tb.autotest_avoid_topics(bot, test_intensity="light") # Medium testing - balanced coverage (6 conversations) results = tb.autotest_avoid_topics(bot, test_intensity="medium") # Thorough testing - comprehensive strategies (10 conversations) results = tb.autotest_avoid_topics(bot, test_intensity="thorough") # Exhaustive testing - all strategies (15 conversations) results = tb.autotest_avoid_topics(bot, test_intensity="exhaustive") ``` ## Comprehensive Example: Wellness Coach Bot Let's create a productivity-focused bot and test its ability to avoid gaming topics: ```python import talk_box as tb # Create a specialized productivity coach bot with structured prompts wellness_bot = tb.ChatBot().provider_model("openai:gpt-4o") # Build a comprehensive prompt using PromptBuilder wellness_prompt = ( tb.PromptBuilder() .persona( role="productivity and wellness coach", expertise="work-life balance, professional development, and healthy lifestyle habits" ) .task_context( "Help people improve their professional productivity, develop better work habits, " "enhance their career skills, and maintain healthy lifestyle choices. Focus on " "practical, actionable advice for real-world improvement." ) .core_analysis([ "Assess productivity challenges and provide practical solutions", "Recommend evidence-based strategies for professional growth", "Suggest healthy lifestyle changes that support career success", "Offer time management and organizational techniques", "Provide guidance on skill development and learning strategies" ]) .avoid_topics([ "video games", "gaming", ]) .output_format([ "Provide specific, actionable advice focused on real-world productivity", "Suggest concrete steps people can take today to improve their situation", "Recommend professional development resources when appropriate", "Include time management tips and healthy habit formation strategies" ]) .final_emphasis( "You are a professional coach focused on helping people succeed in their careers " "and maintain healthy, productive lifestyles. Stay firmly within this domain and " "redirect any entertainment or gaming discussions to productive alternatives." ) ) wellness_bot = wellness_bot.system_prompt(wellness_prompt) # Test the bot's compliance results = tb.autotest_avoid_topics(wellness_bot, test_intensity="thorough") ``` ## Understanding Test Results The `TestResults` object provides rich analysis capabilities: ### Summary Statistics ```python # Get comprehensive summary summary = results.summary print(f"Total tests run: {summary['total_tests']}") print(f"Tests passed: {summary['passed']}") print(f"Tests failed: {summary['failed']}") print(f"Success rate: {summary['success_rate']:.1%}") print(f"Total violations: {summary['violation_count']}") print(f"Average test duration: {summary['avg_duration']:.2f} seconds") # See which topics were tested print(f"Topics tested: {list(summary['topics_tested'].keys())}") print(f"Strategies used: {list(summary['strategies_used'].keys())}") ``` ### Individual Test Results ```python # Examine individual conversation results for i, result in enumerate(results.results): status = "PASSED" if result.completed and not result.violations else "FAILED" print(f"Test {i+1}: {result.topic} ({result.strategy}) - {status}") if result.violations: print(f" Violations: {len(result.violations)}") for violation in result.violations: print(f" - {violation.explanation}") ``` ### Rich HTML Display In notebook environments, `TestResults` automatically displays rich HTML with: ```python # This shows an interactive dashboard with: # - Summary statistics with visual metrics # - Test configuration details # - Individual conversation transcripts # - Violation analysis with highlighted responses results ``` Here are the HTML-formatted results for the tests previously performed on the `wellness_bot`: ## Testing Strategies The function uses multiple adversarial strategies: - **Direct**: straightforward requests for prohibited information - **Indirect**: third-party or hypothetical scenarios - **Emotional Appeal**: urgent or distressing situations - **Hypothetical**: "what if" or theoretical questions - **Role Playing**: professional or academic contexts - **Context Shifting**: starting with acceptable topics, then shifting - **Persistence**: follow-up questions after initial refusal ## Advanced Configuration ### Custom Judge Model Use a specific model for violation evaluation: ```python # Use GPT-4 for more accurate violation detection results = tb.autotest_avoid_topics( bot, test_intensity="thorough", judge_model="gpt-4", verbose=True ) ``` ### Precise Control Override intensity settings for exact control: ```python # Run exactly 8 conversations regardless of intensity level results = tb.autotest_avoid_topics( bot, test_intensity="medium", max_conversations=8 ) ``` ## Export and Analysis Convert results to structured formats for further analysis: ```python # Export to pandas DataFrame df = results.to_dataframe() # Analyze violations by topic violation_summary = df.groupby('topic')['violations'].sum() print("Violations by topic:") print(violation_summary) # Analyze success rates by strategy success_by_strategy = df.groupby('strategy')['status'].apply( lambda x: (x == 'Passed').mean() ) print("\nSuccess rate by strategy:") print(success_by_strategy) # Export detailed results df.to_csv("compliance_test_results.csv") # Create Great Tables report (if great-tables is installed) gt_table = results.to_great_table() gt_table.save("compliance_report.html") ``` ## Best Practices ### Strong Avoid Topics Configuration Use clear, specific language in your avoid topics: ```python # Specific and clear bot = tb.ChatBot().avoid([ "medical diagnosis", "investment recommendations", "legal advice" ]) # With `PromptBuilder` for stronger constraints prompt = ( tb.PromptBuilder() .persona("helpful assistant", "general support") .avoid_topics([ "medical diagnosis", "investment recommendations", "legal advice" ]) .final_emphasis( "You must not provide advice in prohibited domains. " "Always redirect to appropriate professionals." ) ) ``` ### Regular Testing Incorporate avoid topics testing into your development workflow: ```python # Test during development def test_bot_development(): results = tb.autotest_avoid_topics(bot, test_intensity="light") assert results.summary['success_rate'] >= 0.90, "Development bot failing compliance" # Test before deployment def test_bot_production(): results = tb.autotest_avoid_topics(bot, test_intensity="exhaustive") assert results.summary['success_rate'] >= 0.95, "Production bot failing compliance" assert results.summary['violation_count'] == 0, "Zero violations required for production" ``` ### Iterative Improvement Use test results to strengthen your bot's avoid topics behavior: ```python # Analyze failures to improve prompts results = tb.autotest_avoid_topics(bot, test_intensity="thorough") if results.summary['violation_count'] > 0: print("Violations detected: analyzing patterns...") # Look at violation types for result in results.results: if result.violations: print(f"\nTopic: {result.topic}") print(f"Strategy: {result.strategy}") for violation in result.violations: print(f"Issue: {violation.explanation}") if violation.specific_quotes: print(f"Quote: {violation.specific_quotes[0]}") ``` ### Automated Pathway Testing The `autotest_pathways()` function provides comprehensive automated testing for conversational pathway adherence in ChatBots. It validates that your bots properly follow defined conversation flows, gather required information, and progress through expected states while maintaining flexibility for natural dialogue patterns. ## Why Test Pathway Adherence? When you configure a `ChatBot` with conversational pathways, you want confidence that it will consistently follow the structured flow while remaining conversational, even when: - users provide incomplete information or skip steps - conversations branch in unexpected directions - users resist following the structured approach - edge cases and boundary conditions arise - backtracking or correction is needed - tangential discussions occur Manual testing of pathway adherence is time-consuming and inconsistent, especially for complex multi-state pathways with branching logic. The `autotest_pathways()` function automates this process with sophisticated multi-turn adversarial testing strategies. ## Basic Usage The simplest way to test pathway adherence: ```python import talk_box as tb # Create a pathway support_pathway = ( tb.Pathways( title="Customer Support", desc="systematic customer assistance", activation="Customer needs help with an issue" ) .state("intake: gather issue details and contact information") .required(["problem description", "customer contact info"]) .next_state("diagnosis") .state("diagnosis: understand the root cause") .required(["issue category identified"]) .next_state("resolution") .state("resolution: provide solution and confirm satisfaction") .success_condition("customer issue is resolved and confirmed") ) # Create bot with pathway bot = ( tb.ChatBot() .provider_model("openai:gpt-4o") .system_prompt( tb.PromptBuilder() .persona("helpful customer support agent") .pathways(support_pathway) ) ) # Test pathway adherence results = tb.autotest_pathways(bot, test_intensity="medium") # View results print(f"Average adherence: {results.summary['avg_adherence_score']:.1%}") print(f"Tests completed: {results.summary['completed_tests']}/{results.summary['total_tests']}") print(f"State coverage: {results.summary['state_coverage']:.1%}") ``` ## Test Intensity Levels Control the thoroughness of testing with different intensity levels: ```python # Light testing - quick validation (6 tests, 2 strategies) results = tb.autotest_pathways(bot, test_intensity="light") # Medium testing - balanced coverage (12 tests, 4 strategies) results = tb.autotest_pathways(bot, test_intensity="medium") # Thorough testing - comprehensive strategies (20 tests, 6 strategies) results = tb.autotest_pathways(bot, test_intensity="thorough") # Exhaustive testing - all strategies (30 tests, 7 strategies) results = tb.autotest_pathways(bot, test_intensity="exhaustive") ``` ## Testing Strategies The function uses multiple adversarial strategies to probe pathway adherence: - **Direct Flow**: cooperative users who follow the pathway naturally - **Skip States**: users trying to jump ahead or bypass required steps - **Backtrack**: users wanting to go back or change previous information - **Incomplete Info**: users providing partial or vague information - **Tangential**: users trying to discuss topics outside pathway scope - **Resistance**: users resisting the structured approach - **Edge Cases**: boundary conditions and unusual scenarios ## Comprehensive Example: Onboarding Bot ```python import talk_box as tb # Create complex branching pathway onboarding_pathway = ( tb.Pathways( title="User Onboarding", desc="comprehensive new user setup process", activation=["new user registration", "account setup needed"], completion_criteria="user account is fully configured and ready to use", fallback_strategy="if user needs custom setup, escalate to manual assistance" ) # === STATE: welcome === .state("welcome: introduce platform and gather basic info") .required(["user name", "email confirmation"]) .next_state("role_identification") # === STATE: role_identification === .state("role_identification: determine user type and needs") .required(["user role identified"]) .branch_on("business user", id="business_setup") .branch_on("individual user", id="personal_setup") .branch_on("educational user", id="educational_setup") # === STATE: business_setup === .state("business_setup: configure business features") .required(["company name", "team size", "use case"]) .next_state("feature_configuration") # === STATE: personal_setup === .state("personal_setup: configure personal preferences") .required(["personal interests", "usage goals"]) .next_state("feature_configuration") # === STATE: educational_setup === .state("educational_setup: configure educational features") .required(["institution name", "course information"]) .next_state("feature_configuration") # === STATE: feature_configuration === .state("feature_configuration: set up platform features") .required(["key features enabled", "preferences set"]) .next_state("completion") # === STATE: completion === .state("completion: finalize setup and provide tour") .required(["setup confirmed", "initial tour completed"]) .success_condition("user successfully onboarded and ready to use platform") ) # Create sophisticated bot onboarding_bot = ( tb.ChatBot() .provider_model("openai:gpt-4o") .system_prompt( tb.PromptBuilder() .persona("friendly onboarding specialist", "user experience") .pathways(onboarding_pathway) .output_format([ "ask one focused question at a time", "provide clear guidance and context", "confirm understanding before proceeding" ]) .final_emphasis("Follow pathway systematically while maintaining conversational warmth") ) .temperature(0.3) ) # Run comprehensive testing results = tb.autotest_pathways( onboarding_bot, test_intensity="thorough", judge_model="openai:gpt-4", verbose=True ) ``` ## Understanding Test Results View rich results with detailed analysis: ```python # Display comprehensive results in Jupyter results # Access summary statistics programmatically summary = results.summary print(f"Total tests: {summary['total_tests']}") print(f"Average adherence: {summary['avg_adherence_score']:.1%}") print(f"Completion rate: {summary['completion_rate']:.1%}") print(f"State coverage: {summary['state_coverage']:.1%}") print(f"Issues found: {summary['issues_found']}") # Analyze pathway-specific performance for pathway, data in summary['pathway_coverage'].items(): print(f"\n{pathway}:") print(f" Tests: {data['tests']}") print(f" Completed: {data['completed']}") print(f" Avg Adherence: {data['avg_adherence']:.1%}") # Analyze strategy performance for strategy, data in summary['strategy_performance'].items(): print(f"\n{strategy}:") print(f" Tests: {data['tests']}") print(f" Avg Adherence: {data['avg_adherence']:.1%}") ``` ## Advanced Configuration ### Custom Judge Model Use a specific model for pathway evaluation: ```python # Use GPT-4 for more accurate adherence evaluation results = tb.autotest_pathways( bot, test_intensity="thorough", judge_model="openai:gpt-4", verbose=True ) ``` ### Precise Control Override intensity settings for exact control: ```python # Run exactly 15 tests regardless of intensity level results = tb.autotest_pathways( bot, test_intensity="medium", max_tests=15 ) ``` ## Problem Analysis Identify and analyze pathway adherence issues: ```python # Get detailed problem summary problems = results.get_problem_summary() print("Issues requiring attention:") for problem in problems: print(f"\n- {problem['issue']}") print(f" Frequency: {problem['frequency']} occurrences") print(f" Pathways affected: {', '.join(problem['pathways_affected'])}") print(f" Strategies affected: {', '.join(problem['strategies_affected'])}") # Get adherence score distribution distribution = results.get_adherence_distribution() for category, count in distribution.items(): if count > 0: print(f"{category}: {count} tests") ``` ## Individual Test Analysis Examine specific test results: ```python # Look at individual test results for result in results.results: if result.pathway_adherence_score < 0.7: # Focus on problematic tests print(f"\nPathway: {result.pathway_title}") print(f"Strategy: {result.strategy.value}") print(f"Adherence: {result.pathway_adherence_score:.1%}") print(f"States achieved: {result.states_achieved}") print(f"Issues: {result.issues}") # Examine the conversation for message in result.conversation.messages: role = "User" if message.role == "user" else "Bot" print(f" {role}: {message.content[:100]}...") ``` ## Export and Analysis Export results for further analysis: ```python # Export summary data import json export_data = { "summary": results.summary, "problems": results.get_problem_summary(), "distribution": results.get_adherence_distribution(), "test_config": results.config } with open("pathway_test_results.json", "w") as f: json.dump(export_data, f, indent=2, default=str) print("Results exported to pathway_test_results.json") ``` ## Best Practices ### Development Workflow Incorporate pathway testing into your development process: ```python # Quick validation during development def test_pathway_development(): results = tb.autotest_pathways(bot, test_intensity="light") assert results.summary['avg_adherence_score'] >= 0.7, "Development bot needs pathway improvements" # Comprehensive testing before deployment def test_pathway_production(): results = tb.autotest_pathways(bot, test_intensity="exhaustive") assert results.summary['avg_adherence_score'] >= 0.85, "Production bot failing pathway adherence" assert results.summary['completion_rate'] >= 0.9, "Too many test failures" ``` ### Iterative Improvement Use test results to strengthen pathway adherence: ```python # Analyze failures to improve pathway design results = tb.autotest_pathways(bot, test_intensity="thorough") if results.summary['avg_adherence_score'] < 0.8: print("Pathway adherence needs improvement...") # Look at problem patterns problems = results.get_problem_summary() for problem in problems[:5]: # Top 5 issues print(f"\nIssue: {problem['issue']}") print(f"Frequency: {problem['frequency']}") # Look at specific strategies that cause this issue affected_strategies = problem['strategies_affected'] print(f"Problematic strategies: {', '.join(affected_strategies)}") ``` ### Pathway Design Validation Use testing to validate pathway design decisions: ```python # Test different pathway variations pathway_v1 = create_basic_pathway() pathway_v2 = create_improved_pathway() bot_v1 = create_bot_with_pathway(pathway_v1) bot_v2 = create_bot_with_pathway(pathway_v2) results_v1 = tb.autotest_pathways(bot_v1, test_intensity="medium") results_v2 = tb.autotest_pathways(bot_v2, test_intensity="medium") print(f"V1 Adherence: {results_v1.summary['avg_adherence_score']:.1%}") print(f"V2 Adherence: {results_v2.summary['avg_adherence_score']:.1%}") if results_v2.summary['avg_adherence_score'] > results_v1.summary['avg_adherence_score']: print("V2 shows better pathway adherence!") ``` ## Integration with CI/CD Incorporate pathway testing into automated pipelines: ```python # pytest integration def test_pathway_compliance(): """Test that production bot maintains pathway adherence.""" bot = create_production_bot() results = tb.autotest_pathways(bot, test_intensity="thorough") # Set quality gates assert results.summary['avg_adherence_score'] >= 0.85 assert results.summary['completion_rate'] >= 0.9 assert results.summary['issues_found'] <= 5 # No critical issues in specific strategies strategy_performance = results.summary['strategy_performance'] for strategy, data in strategy_performance.items(): if strategy in ['direct_flow', 'incomplete_info']: assert data['avg_adherence'] >= 0.9, f"Critical strategy {strategy} failing" ``` ## Summary Pathway testing provides comprehensive validation of conversational flow adherence: - **Automated Testing**: systematic validation with multiple adversarial strategies - **Rich Analysis**: detailed reporting with adherence scores and issue identification - **Quality Assurance**: integration with development workflows and CI/CD pipelines - **Iterative Improvement**: data-driven pathway optimization and design validation The `autotest_pathways()` function enables you to build confidence in your ChatBot's ability to guide users through complex, multi-step processes while maintaining natural conversation patterns. ### Tool System The Talk Box tool system provides a powerful way to extend your AI assistants with custom functionality and pre-built utilities. This guide covers everything from creating your first tool to advanced observability and debugging techniques. ## Quick Start The fastest way to get started with Talk Box tools is to use the built-in collection that handles common tasks, then gradually add your own custom tools as your needs grow. This section walks you through the essential patterns: using pre-built tools for immediate functionality, creating simple custom tools for your specific needs, and combining both approaches to build powerful AI assistants. ### Using Built-in Tools Talk Box comes with a comprehensive collection of ready-to-use tools that handle the most common tasks you encounter when building AI assistants. These tools have been carefully designed and tested to work reliably in production environments, covering everything from mathematical calculations and text processing to data validation and network operations. Using built-in tools is the fastest way to get started and add immediate functionality to your AI assistant without writing any code: Here's an example where we add specific built-in tools using their names: ```{python} import talk_box as tb bot = tb.ChatBot().tools(["calculate", "validate_email", "current_time"]).model("gpt-4") bot ```
Notice how the HTML representation now shows a dedicated **Tools** section that displays the actual tool names rather than just showing "Tools: 3 enabled". This makes it much easier to see exactly which capabilities are available to your ChatBot. Or add all built-in tools at once: ```{python} bot = tb.ChatBot().tools("all").model("gpt-4") bot ``` ### Creating Custom Tools While built-in tools provide excellent coverage for common tasks, the real power of Talk Box comes from creating custom tools tailored to your specific domain and business logic. Custom tools allow you to integrate your existing systems, APIs, and business processes directly into your AI assistant's capabilities. The `@tb.tool` decorator makes this process straightforward, automatically handling parameter validation, error management, and integration with the Talk Box ecosystem. Let's start with a simple example to demonstrate the basic pattern: ```{python} import talk_box as tb @tb.tool def say_hello(name: str) -> str: """Simple tool that says hello.""" return f"Hello, {name}!" # Use with ChatBot bot = tb.ChatBot().tools([say_hello]).model("gpt-4") bot ```
For more control over your tool's behavior, use the full decorator syntax: ```{python} import talk_box as tb @tb.tool( name="greet_user", description="Generate a personalized greeting" ) def greet_user(name: str, time_of_day: str = "day") -> tb.ToolResult: greeting = f"Good {time_of_day}, {name}! How can I help you today?" return tb.ToolResult(data=greeting) # Use with ChatBot bot = tb.ChatBot().tools([greet_user]).model("gpt-4") ``` #### Decorator Forms: `@tb.tool` vs `@tb.tool(...)` There are two equivalent ways to declare a tool: 1. **Bare form.** Quickest path for when you don't need extra metadata: ```python @tb.tool def say_hello(name: str) -> str: """Simple greeting.""" return f"Hello, {name}!" ``` 2. **Configured form.** Supply explicit metadata or options: ```python @tb.tool( name="greet_user", description="Generate a personalized greeting", examples=["greet_user('Ada','morning') -> Good morning, Ada!"], timeout_seconds=5, tags=["greeting", "demo"], ) def greet_user(name: str, time_of_day: str = "day") -> str: return f"Good {time_of_day}, {name}!" ``` Both forms *register* the function immediately in the global tool registry when the module is imported. Registration alone does not make the tool active for a specific `ChatBot`. To actually enable it for a bot, you must still pass the function to `.tools([...])`: ```python bot = tb.ChatBot().tools([say_hello, greet_user]).model("gpt-4") ``` Why two steps? - **Registration**: makes the tool discoverable globally. - **Attachment**: explicitly scopes which tools a particular bot can use (avoids accidental capability leakage). If you prefer name-based inclusion for built-ins you can mix forms: ```python bot = tb.ChatBot().tools([ say_hello, # custom (registered by decorator) "calculate", # built-in by name greet_user, # another custom ]).model("gpt-4") ``` Future convenience helpers may allow adding custom tools by name; for now, pass the function object for custom tools and string names for built-ins. ### Mixing Custom and Built-in Tools One of the most powerful aspects of Talk Box is the ability to seamlessly combine your custom business logic with the comprehensive library of built-in utilities. This hybrid approach lets you focus on implementing domain-specific functionality while leveraging proven, tested tools for common operations like data validation, calculations, and text processing. The unified `.tools()` API handles both custom and built-in tools identically, making it easy to create sophisticated AI assistants that blend your unique requirements with general-purpose capabilities: ```python import talk_box as tb @tb.tool(name="check_inventory", description="Check product stock") def check_inventory(product_id: str) -> tb.ToolResult: # Your business logic here stock = {"product": product_id, "quantity": 42, "available": True} return tb.ToolResult(data=stock) # Mix custom tools with built-in ones bot = ( tb.ChatBot() .tools([ check_inventory, # Custom tool (function) "calculate", # Built-in tool (string name) "validate_email", # Built-in tool (string name) ]) .model("gpt-4") ) ``` ## What Is a Tool? A tool is a Python function plus structured metadata that the ChatBot is allowed to call to accomplish a user goal. Think of it as a safe, self‑describing capability boundary: - Code the model can invoke (your function) - A name & description the model reads to decide when to use it - A parameter schema inferred from your signature - A standardized result object (`ToolResult`) so the rest of the system can observe, debug, and chain outputs If a function is not attached via `.tools(...)`, it is invisible to the model—even if it is registered globally. This explicit opt‑in prevents accidental capability leakage. ### Mental Model: Registration vs Attachment | Phase | What Happens | Trigger | Scope | Purpose | |-------|--------------|---------|-------|---------| | Registration | Function is wrapped & stored in the global registry | Import time when `@tb.tool` decorator executes | Global process | Discoverability & inspection | | Attachment | Specific tools chosen for a bot instance | Calling `ChatBot().tools([...])` | That bot only | Capability authorization | Guideline: Treat the registry like a catalog and `.tools([...])` like a firewall rule list. Only attach what each assistant truly needs. ## Core Concepts Now that you've seen the basics of using and creating tools, let's dive deeper into the fundamental concepts that power the Talk Box tool system. Understanding these core building blocks will help you design more effective tools, leverage advanced features, and troubleshoot issues when they arise. These concepts form the foundation for everything from simple utility functions to complex business integrations. ### Tool Anatomy When you create a tool with the `@tb.tool` decorator, Talk Box automatically handles the technical details for you. However, it's helpful to understand what's happening behind the scenes. Every tool, whether built-in or custom, has three essential components: 1. **Metadata**: name, description, and parameter schema that help the AI understand what the tool does 2. **Context**: runtime information about the conversation and execution environment 3. **Implementation**: the actual logic that processes inputs and returns results Here's how these components work together in a practical tool that needs runtime context information: ```{python} import talk_box as tb @tb.tool( name="format_currency", description="Format a number as currency with proper symbols and decimal places" ) def format_currency(context: tb.ToolContext, amount: float, currency: str = "USD") -> tb.ToolResult: # Access context information when you need it timestamp = context.timestamp # Implement the tool logic symbols = {"USD": "$", "EUR": "€", "GBP": "£"} symbol = symbols.get(currency, currency) formatted = f"{symbol}{amount:,.2f}" # Return structured result return tb.ToolResult( data=formatted, metadata={ "original_amount": amount, "currency": currency, "formatted_at": timestamp } ) ``` The `context` parameter is completely optional. Only include it in your function signature when your tool actually needs runtime information like timestamps, user IDs, or observability features. Talk Box automatically detects whether your function expects context and only passes it when needed. This structure ensures that tools are predictable, debuggable, and provide rich information back to both the AI and your application. Let's explore each of these components in detail to understand how they work and how you can leverage them effectively in your own tools. ### Tool Context The `ToolContext` provides access to runtime information: ```python import talk_box as tb @tb.tool(name="context_example", description="Show context usage") def context_example(context: tb.ToolContext, message: str) -> tb.ToolResult: # Access conversation metadata user_id = context.conversation_id timestamp = context.timestamp # Access observability (if enabled) if context.observer: context.observer.log("Processing message", {"length": len(message)}) return tb.ToolResult( data=f"Message '{message}' processed at {timestamp}", metadata={"user": user_id, "message_length": len(message)} ) ``` The `ToolContext` becomes valuable when you need to build tools that are aware of their environment. For example: - **User-specific behavior**: a customer service tool might look up different data based on which user is asking - **Conversation continuity**: tools can reference previous interactions or maintain state across multiple calls - **Security and auditing**: track who used which tools and when for compliance or debugging - **Personalization**: adjust tool behavior based on user preferences or conversation history - **Performance monitoring**: log tool usage patterns to optimize your AI assistant's performance Without context, tools operate in isolation. With context, they become intelligent components that can adapt to their environment and provide richer, more personalized experiences. The following table summarizes what you can access from `context` inside a tool. | Name | Type | Description | |------|------|-------------| | `conversation_id` | `str | None` | Identifier of the active conversation (if provided). | | `user_id` | `str | None` | Identifier of the end user (for personalization / logging). | | `session_id` | `str | None` | Session or application run identifier (multi-request grouping). | | `conversation_history` | `list[dict]` | Prior messages (role/content dicts); use `get_last_messages()` for slices. | | `user_metadata` | `dict` | Arbitrary user data; preferences often under `user_metadata['preferences']`. | | `tool_registry` | `ToolRegistry | None` | Registry instance; inspect or look up other tools if needed. | | `extra` | `dict` | Extension bag for app-specific values you inject. | | `get_last_messages(n=5)` | method | Return the last `n` conversation messages (safe if history empty). | | `get_user_preference(key, default=None)` | method | Convenience lookup from `user_metadata['preferences']`. | Here's a minimal pattern inside a tool: ```python @tb.tool(name="inspect_context", description="Show context essentials") def inspect_context(context: tb.ToolContext) -> tb.ToolResult: summary = { "user": context.user_id, "last_messages": context.get_last_messages(2), "has_registry": context.tool_registry is not None, "created_at": context.timestamp.isoformat(), } return tb.ToolResult(data=summary, display_format="json") ``` ### Tool Results Tools **must** return `ToolResult` objects to maintain consistency, reliability, and rich communication with the AI system. Here's how to leverage `ToolResult` effectively: ```python import talk_box as tb @tb.tool(name="rich_result", description="Return rich result data") def rich_result(context: tb.ToolContext, query: str) -> tb.ToolResult: return tb.ToolResult( data={ "answer": f"Result for: {query}", "confidence": 0.95, "sources": ["source1", "source2"] }, metadata={ "processing_time": 0.123, "model_used": "analysis-v2" }, success=True ) ``` While it might seem simpler to return plain strings or dictionaries, the `ToolResult` structure provides many advantages that make your AI assistant more robust and intelligent. The `ToolResult` object serves as a standardized contract between your tools and the Talk Box system, ensuring that results are predictable, debuggable, and provide rich context back to both the AI and your application. This structured approach enables advanced features like error handling, observability, metadata tracking, and success/failure indicators that would be impossible with simple return values. All of this matters for the following reasons: - **Structured Communication**: the AI receives consistent, predictable data formats regardless of which tool was called, making it easier to process and act on results. - **Rich Metadata**: beyond the core data, you can include processing times, confidence scores, source information, and other contextual details that help the AI make better decisions. - **Error Handling**: built-in success/failure indicators and error messages allow the AI to gracefully handle problems and potentially retry with different approaches. - **Observability**: the standardized format enables comprehensive monitoring, debugging, and performance analysis across all your tools. Plain returns are auto-coerced for convenience, but adopting `ToolResult` early unlocks richer debugging, consistent downstream handling, and clearer model feedback. ## Available Built-in Tools Talk Box comes with a comprehensive collection of built-in tools that handle common tasks. These tools are production-ready and follow best practices for error handling, performance, and usability. You can use them immediately without any setup or configuration. The Talk Box Tool Box includes these built-in tools: ### Math and Calculations - **`calculate`**: perform mathematical calculations - **`number_sequence`**: generate numeric sequences with start, stop, and step ### Text and Data Processing - **`text_stats`**: get statistics about text (word count, character count, etc.) - **`convert_case`**: convert text between different cases (upper, lower, title, etc.) - **`parse_json`**: parse and validate JSON strings - **`to_json`**: convert data structures to JSON strings - **`sort_list`**: sort lists of values ### Date and Time - **`current_time`**: get current date and time information - **`date_diff`**: calculate the difference between two dates ### URL and Path Utilities - **`parse_url`**: parse URLs into their components - **`url_encode_decode`**: URL encode/decode strings - **`path_info`**: extract information from file paths ### Validation and Utilities - **`validate_email`**: validate email address formats - **`generate_uuid`**: generate UUID strings View all available tools: ```{python} import talk_box as tb # Load the tool box first to make tools available tb.load_tool_box() # Get the global registry to see what tools are available registry = tb.get_global_registry() all_tools = registry.get_all_tools() # Filter for built-in tools (those with "tool_box" in tags) builtin_tools = [tool for tool in all_tools if tool.tags and "tool_box" in tool.tags] print(f"Built-in tools available ({len(builtin_tools)}):") for tool in builtin_tools: print(f" - {tool.name}: {tool.description}") ``` ### Exploring Built-in Tool Details You can inspect the internals of any built-in tool to understand its parameters, description, and functionality: ```{python} # Get detailed information about a specific tool calc_tool = tb.get_builtin_tool("calculate") print(f"Name: {calc_tool.name}") print(f"Description: {calc_tool.description}") print(f"Category: {calc_tool.category}") ``` ```{python} # Explore the email validator tool email_tool = tb.get_builtin_tool("validate_email") print(f"Name: {email_tool.name}") print(f"Description: {email_tool.description}") print(f"Category: {email_tool.category}") print(f"Tags: {email_tool.tags}") ``` ```{python} # See what categories are available and tools in each registry = tb.get_global_registry() # Load the tool box first tb.load_tool_box() # Now explore by category using the actual categories data_tools = registry.get_tools_by_category(tb.ToolCategory.DATA) web_tools = registry.get_tools_by_category(tb.ToolCategory.WEB) print("Data processing tools:") for tool in data_tools[:3]: # Show first 3 to keep output manageable print(f" - {tool.name}: {tool.description}") print("\nWeb-related tools:") for tool in web_tools: print(f" - {tool.name}: {tool.description}") ``` These built-in tools provide immediate functionality and can be combined with your custom tools to create powerful AI assistants. The tools are organized by category to help you find the right functionality for your use case. ## Understanding the Global Registry Talk Box uses a global registry to manage all available tools in your application. This registry acts as a central repository that keeps track of both built-in tools and any custom tools you create with the `@tb.tool` decorator. Understanding how this registry works is essential for effectively managing your tool ecosystem. ### How the Registry Works When you use the `@tb.tool` decorator, your tool is automatically registered in the global registry, making it available for use by any ChatBot in your application: ```python import talk_box as tb @tb.tool(name="my_custom_tool") def my_custom_tool(context: tb.ToolContext, input_data: str) -> tb.ToolResult: return tb.ToolResult(data=f"Processed: {input_data}") # Tool is now automatically available in the global registry registry = tb.get_global_registry() print("Available tools:", [tool.name for tool in registry.get_all_tools()]) ``` Built-in tools are also loaded into the global registry when you first use them via the `.tools()` method. This creates a unified system where all tools are managed consistently. ### Managing the Registry You can inspect and manage the global registry directly when needed: ```{python} import talk_box as tb # Get the global registry registry = tb.get_global_registry() # See all registered tools all_tools = registry.get_all_tools() print(f"Total tools registered: {len(all_tools)}") ``` ```{python} # Get tools by category using actual enum values data_tools = registry.get_tools_by_category(tb.ToolCategory.DATA) custom_tools = registry.get_tools_by_category(tb.ToolCategory.CUSTOM) print("Data tools:", [t.name for t in data_tools[:3]]) # Show first 3 print("Custom tools:", [t.name for t in custom_tools]) ``` ```{python} # Check if a specific tool exists calc_tool = registry.get_tool("calculate") if calc_tool: print(f"Calculator tool: {calc_tool.description}") else: print("Calculator tool not found") ``` ### When to Clear the Registry In certain scenarios, you might want to start with a clean slate by clearing the global registry. This is particularly useful for: - **Testing environments** where you want isolated tool sets - **Specialized applications** that only need specific custom tools - **Multi-tenant systems** where different contexts need different tool sets ```python import talk_box as tb # Clear all tools from the registry tb.clear_global_registry() # Now only register the tools you specifically need @tb.tool(name="specialized_tool") def specialized_tool(context: tb.ToolContext) -> tb.ToolResult: return tb.ToolResult(data="Specialized functionality") # This bot will only have access to your custom tool bot = tb.ChatBot().tools([specialized_tool]).model("gpt-4") ``` Understanding the global registry helps you make informed decisions about tool management and ensures you have full control over what capabilities are available in your AI assistant. ## Tool Selection Strategies Choosing the right combination of tools depends on your application's needs. Talk Box supports three main strategies for tool selection, each optimized for different scenarios. Consider your specific requirements for control, functionality, and development speed when selecting an approach. ### 1. Custom Tools Only (Domain-Specific) Best for specialized applications where you need full control: ```python import talk_box as tb # Start with a clean slate and remove all built-in tools tb.clear_global_registry() @tb.tool(name="process_order", description="Process customer order") def process_order(context: tb.ToolContext, order_data: dict) -> tb.ToolResult: # Your business logic return tb.ToolResult(data={"order_id": "12345", "status": "processed"}) @tb.tool(name="check_inventory", description="Check product availability") def check_inventory(context: tb.ToolContext, product_id: str) -> tb.ToolResult: # Your inventory logic return tb.ToolResult(data={"available": True, "quantity": 42}) # Bot with only your custom tools bot = tb.ChatBot().tools([process_order, check_inventory]).model("gpt-4") ``` ### 2. Selective Built-in Tools (Recommended) Cherry-pick useful built-in tools for your use case: ```python # E-commerce assistant example bot = ( tb.ChatBot() .tools([ process_order, # Custom business logic check_inventory, # Custom inventory system "calculate", # Built-in: price calculations "validate_email", # Built-in: customer emails "current_time", # Built-in: order timestamps "generate_uuid", # Built-in: order IDs ]) .model("gpt-4") ) ``` ### 3. All Built-in Tools (Quick Prototyping) Load all built-in tools for experimentation: ```python # Get everything, useful for exploration bot = tb.ChatBot().tools("all").model("gpt-4") ``` Each strategy has its own benefits: custom-only provides maximum control and minimal dependencies, selective built-in offers the best balance of functionality and specificity, while loading all tools gives you maximum capability for experimentation and rapid prototyping. ## Advanced Tool Features Beyond basic tool creation and usage, Talk Box provides advanced features for monitoring, debugging, and organizing tools in production environments. These capabilities help you build robust, maintainable AI systems with full visibility into tool behavior. ### Tool Observability (Advanced) Understanding how your tools behave in production is critical for maintaining reliable AI assistants. Talk Box's observability system provides comprehensive monitoring capabilities, tracking everything from execution times and success rates to detailed performance metrics and error patterns. This visibility helps you identify bottlenecks, optimize performance, and ensure your tools are working as expected under real-world conditions. Here's how to set up monitoring for your tools: ```python import talk_box as tb # Create observer with metrics tracking observer = tb.ToolObserver( track_performance=True, track_usage=True, track_errors=True ) # Create bot with observability bot = ( tb.ChatBot() .tools(["calculate", "validate_email", my_custom_tool]) .observer(observer) .model("gpt-4") ) # After running conversations, get metrics metrics = observer.get_metrics() print(f"Tool calls: {metrics.total_calls}") print(f"Average execution time: {metrics.avg_execution_time}") print(f"Error rate: {metrics.error_rate}") ``` ### Tool Debugging (Advanced) During development, you need detailed visibility into what your tools are doing, how they're being called, and what data they're processing. Talk Box's debugging system provides rich, real-time insights into tool execution with beautiful console output, detailed parameter inspection, and comprehensive execution traces. This makes it much easier to identify issues, understand tool behavior, and optimize your implementations. Here's how to enable debugging for your development workflow: ```python import talk_box as tb # Create debugger with Rich UI debugger = tb.ToolDebugger() # Enable debug mode bot = ( tb.ChatBot() .tools([my_tool]) .debugger(debugger) .model("gpt-4") ) # Debugger will show real-time execution info # Export debug reports debugger.export_debug_report("debug_session.json") ``` ### Tool Categories and Organization (Advanced) As your AI assistant grows more sophisticated and incorporates more tools, organizing them becomes essential for maintainability and discoverability. Talk Box automatically categorizes tools based on their functionality, making it easy to find related tools, manage subsets of functionality, and understand what capabilities are available in your system. This organizational system is particularly valuable when building complex AI assistants that need different tool sets for different contexts or user roles: ```python import talk_box as tb registry = tb.get_global_registry() # Tools are automatically categorized data_tools = registry.get_tools_by_category(tb.ToolCategory.DATA) web_tools = registry.get_tools_by_category(tb.ToolCategory.WEB) system_tools = registry.get_tools_by_category(tb.ToolCategory.SYSTEM) print("Data tools:", [t.name for t in data_tools[:3]]) # Show first 3 print("Web tools:", [t.name for t in web_tools]) print("System tools:", [t.name for t in system_tools]) ``` These advanced features provide the foundation for building enterprise-grade AI applications with proper monitoring, debugging capabilities, and organized tool management. ### Error Handling in Tools Robust error handling is the foundation of reliable AI assistants that can gracefully handle unexpected situations and provide helpful feedback to users. In production environments, tools will encounter invalid inputs, network failures, missing resources, and other error conditions that need to be handled elegantly. Well-designed error handling not only prevents crashes but also guides the AI toward alternative approaches and helps users understand what went wrong and how to fix it. Always anticipate potential failure modes and provide meaningful error messages to help both the AI and end users understand what went wrong. Here's how to implement comprehensive error handling in your tools: ```python import talk_box as tb @tb.tool(name="safe_divide", description="Safely divide two numbers") def safe_divide(context: tb.ToolContext, a: float, b: float) -> tb.ToolResult: try: if b == 0: return tb.ToolResult( data=None, error="Division by zero is not allowed", success=False ) result = a / b return tb.ToolResult( data=result, metadata={"operation": "division", "inputs": [a, b]}, success=True ) except Exception as e: return tb.ToolResult( data=None, error=f"Calculation error: {str(e)}", success=False ) ``` Proper error handling makes your tools more reliable and provides better user experiences. The AI can use error information to suggest alternatives or ask for corrected input. ## Best Practices Following these best practices will help you create tools that are reliable, maintainable, and effective in production environments. These guidelines are based on experience building AI systems at scale. ### 1. Tool Design Each tool should do one thing well. Having well-written descriptions help to make a tool's purpose obvious to the LLM. When it comes to parameter names and their types, be descriptive with those. Here's an example of what to do and what *not* to do: ```python import talk_box as tb # Good: Focused, clear purpose @tb.tool( name="validate_credit_card", description="Validate credit card number using Luhn algorithm" ) def validate_credit_card(context: tb.ToolContext, card_number: str) -> tb.ToolResult: # Implementation... pass # Avoid: Too broad, unclear purpose @tb.tool(name="process_payment", description="Handle payments") def process_payment(context: tb.ToolContext, **kwargs) -> tb.ToolResult: # Too many responsibilities pass ``` ### 2. Parameter Design Well-designed parameters are crucial for creating tools that are both powerful and easy for AI models to use correctly. The way you structure your parameters directly impacts how effectively the AI can understand what inputs are needed, what formats are expected, and how to validate the data before processing. For complex data structures, using clear validation patterns and providing helpful error messages when parameters are malformed will make your tools much more reliable and user-friendly. Here's how to design robust parameter validation for complex data: ```python import talk_box as tb @tb.tool( name="create_user_profile", description="Create a new user profile with validation" ) def create_user_profile(context: tb.ToolContext, user_data: dict) -> tb.ToolResult: # user_data should be: {"name": str, "email": str, "age": int} required_fields = ["name", "email", "age"] for field in required_fields: if field not in user_data: return tb.ToolResult( data=None, error=f"Missing required field: {field}", success=False ) # Validation and processing... return tb.ToolResult(data={"profile_id": "12345", "created": True}) ``` ### 3. Performance Considerations Here are a few ways to keep perference in mind when creating tools: - keep tool execution fast (< 1 second when possible) - use async patterns for I/O operations - cache expensive computations - provide progress feedback for long operations ```python import asyncio import talk_box as tb @tb.tool(name="fetch_data", description="Fetch data from API") async def fetch_data(context: tb.ToolContext, url: str) -> tb.ToolResult: try: # Use async HTTP client async with httpx.AsyncClient() as client: response = await client.get(url, timeout=5.0) return tb.ToolResult(data=response.json()) except Exception as e: return tb.ToolResult(data=None, error=str(e), success=False) ``` These performance considerations become critical as your AI assistant scales to handle more users and more complex operations. Async patterns are especially important for tools that need to make network requests or access databases. ### 4. Testing Tools Comprehensive testing ensures your tools work correctly across different scenarios and edge cases, from happy path executions to error conditions and boundary cases. Testing custom tools is especially important because they often integrate with external systems, process user data, or handle business-critical operations. Talk Box provides specialized testing utilities to make this process straightforward, including mock contexts, parameter validation helpers, and result verification tools. Here's how to implement thorough testing for your custom tools: ```python import pytest import talk_box as tb def test_greet_user(): context = tb.MockToolContext() result = greet_user(context, name="Alice", time_of_day="morning") assert result.success assert "Good morning, Alice" in result.data assert result.error is None # Use the testing utilities def test_with_utilities(): # Test tool execution result = tb.test_tool(greet_user, name="Bob") assert result.success # Test parameter validation with pytest.raises(ValueError): tb.test_tool(greet_user) # Missing required 'name' parameter ``` Regular testing helps catch issues early and ensures your tools continue to work as expected when you make changes to your codebase or update dependencies. ## Tool Advertising: The Key to Effective Tool Usage The most critical aspect of successful tool integration is **explicitly advertising your tools in the system prompt**. Think of the system prompt as an attention mechanism: if you don't tell the LLM about available tools and when to use them, it will often attempt to answer questions using its training data instead of leveraging your carefully crafted tools. This section demonstrates how to create system prompts that effectively direct the LLM's attention to your tools, ensuring they are used appropriately and consistently. ### The Attention Problem Without proper tool advertising, LLMs exhibit these problematic behaviors: - **Tool Blindness**: ignoring available tools and attempting to answer from training data - **Inconsistent Usage**: sometimes using tools, sometimes not, leading to unpredictable behavior - **Incorrect Tool Selection**: choosing the wrong tool for a task when multiple options exist - **Missed Opportunities**: failing to combine tools effectively for complex workflows The solution is to explicitly guide the LLM's attention using structured system prompts that clearly advertise available tools and their intended usage patterns. Here are practical examples that show how to do this effectively. ### Customer Service Bot: Explicit Tool Advertising This example demonstrates how to create a customer service assistant that reliably uses tools for order management and customer verification. The key is explicitly directing the AI's attention to each tool and when to use it. ```{python} import talk_box as tb @tb.tool(name="lookup_order", description="Look up customer order") def lookup_order(context: tb.ToolContext, order_id: str) -> tb.ToolResult: # Your order lookup logic return tb.ToolResult(data={"order_id": order_id, "status": "shipped"}) @tb.tool(name="process_refund", description="Process customer refund") def process_refund(context: tb.ToolContext, order_id: str, reason: str) -> tb.ToolResult: # Your refund logic return tb.ToolResult(data={"refund_id": "RF12345", "amount": 99.99}) system_prompt = ( tb.PromptBuilder() .persona( "helpful customer service assistant", "resolving customer issues efficiently and professionally" ) .task_context( "use tools to handle customer inquiries about orders, process refunds, and verify info" ) .focus_on( "using the appropriate tools for each customer request to provide accurate assistance" ) .structured_section("Tool Usage Guidelines", [ "use lookup_order to find customer order information", "use process_refund for approved refund requests", "always verify customer email addresses using validate_email", "include timestamps using current_time for all transactions", "generate reference numbers with generate_uuid when needed" ]) ) bot = ( tb.ChatBot() .system_prompt(system_prompt) .tools([ lookup_order, process_refund, "validate_email", # For customer verification "current_time", # For timestamps "generate_uuid", # For reference numbers ]) .model("gpt-4") ) bot ```
This example uses clear, action-oriented guidance in the `"Tool Usage Guidelines"` section to explicitly map user requests to specific tools. The prompt uses imperative language (`"use lookup_order to find"`, `"always verify"`) to make tool usage feel mandatory rather than optional. By listing each tool with its specific trigger condition, the AI knows exactly when to reach for each capability, preventing it from attempting to answer order questions from memory or providing generic customer service responses. ### Content Analysis Bot: Tool-First Approach This content analysis bot demonstrates how to ensure AI models consistently use specialized analysis tools rather than relying on their training data for text processing tasks. The approach emphasizes workflow-based tool advertising. ```{python} import talk_box as tb @tb.tool(name="sentiment_analysis", description="Analyze text sentiment") def sentiment_analysis(context: tb.ToolContext, text: str) -> tb.ToolResult: # Your sentiment analysis logic return tb.ToolResult(data={"sentiment": "positive", "confidence": 0.85}) system_prompt = ( tb.PromptBuilder() .persona( "content analysis expert", "text processing and deriving actionable insights" ) .task_context( "analyze text content for sentiment, statistics, and patterns using analysis tools" ) .focus_on( "providing thorough analysis with clear confidence indicators and structured results" ) .structured_section("Analysis Workflow", [ "use sentiment_analysis to determine emotional tone of text", "use text_stats to provide detailed metrics about text content", "format all results as structured JSON using to_json", "use generate_uuid to create unique identifiers for analysis sessions", ]) .output_format( "provide confidence scores and supporting evidence in structured JSON format" ) ) bot = ( tb.ChatBot() .system_prompt(system_prompt) .tools([ sentiment_analysis, "text_stats", # Text metrics "to_json", # Structure results "generate_uuid", # Unique identifiers ]) .model("gpt-4") ) bot ```
This example uses a workflow-based approach to tool advertising, organizing tools into logical sequences (`"Analysis Workflow"`) that mirror how a human expert would approach text analysis. The prompt establishes the persona as a `"content analysis expert"` and then immediately directs attention to tool-based processing. The inclusion of output formatting requirements (`"structured JSON format"`) reinforces that all results must flow through the `to_json` tool, creating a consistent pattern of tool dependency that prevents the AI from providing unstructured responses. ### Data Processing Bot: Enforcing Tool Usage This data processing example shows how to create an AI assistant that never attempts manual data manipulation, instead requiring all operations to go through validated, auditable tools. The strategy focuses on workflow enforcement and transparency requirements. ```{python} import talk_box as tb @tb.tool(name="clean_dataset", description="Clean and validate dataset") def clean_dataset(context: tb.ToolContext, data: list) -> tb.ToolResult: # Your data cleaning logic cleaned = [item for item in data if item is not None] return tb.ToolResult( data=cleaned, metadata={"original_count": len(data), "cleaned_count": len(cleaned)} ) system_prompt = ( tb.PromptBuilder() .persona("data processing specialist", "cleaning, validation, and statistical analysis") .task_context( "use tools to clean data, perform calculations, and ensure data quality" ) .focus_on( "maintaining data integrity while reporting on all transformations and quality metrics." ) .structured_section("Data Processing Workflow", [ "use clean_dataset to remove null values and validate data quality", "use calculate for statistical analysis and data summaries", "use sort_list for organizing data collections when needed" ]) .output_format( "format all output as JSON using to_json, including metadata about transformations" ) .critical_constraint( "always report data quality metrics before and after processing to ensure transparency" ) ) bot = ( tb.ChatBot() .system_prompt(system_prompt) .tools([ clean_dataset, "calculate", # Statistical calculations "to_json", # Format results "sort_list", # Organize data collections ]) .model("gpt-4") ) bot ```
This example demonstrates enforcement-oriented tool advertising, using constraints and workflow requirements to make tool usage inevitable. The `"Data Processing Workflow"` section creates a mandatory sequence where each step depends on a specific tool, while the `.critical_constraint()` method adds an accountability layer that requires transparency reporting. The persona as a `"data processing specialist"` combined with explicit workflow steps ensures the AI understands that manual data processing would be unprofessional and error-prone, making tool usage the only acceptable approach. ## Conclusion The Talk Box tool system provides a comprehensive foundation for building powerful AI assistants that can integrate with your existing systems and business logic. From simple utility functions to complex domain-specific operations, tools extend your AI's capabilities beyond what's possible with language models alone. Here are some key takeaways for successful tool integration: - **Start simple**: begin with built-in tools for common tasks, then add custom tools as needed - **Design thoughtfully**: create focused tools with clear purposes, robust error handling, and comprehensive testing - **Advertise effectively**: use structured system prompts to guide your AI toward consistent tool usage - **Monitor and optimize**: leverage observability features to understand tool performance and usage patterns - **Scale systematically**: use the global registry and categorization system to manage growing tool ecosystems Whether you're building a content analysis system or a data processing pipeline, the combination of well-designed tools and thoughtful system prompts will determine your success. Focus on creating reliable, focused tools and guiding your AI to use them effectively. ### Domain Vocabulary The `VocabularyTerm` class enables AI systems to correctly understand and use specialized terminology within specific business, technical, or professional contexts. By providing explicit definitions and multilingual support, vocabulary terms ensure consistent interpretation of domain-specific language that might otherwise be misunderstood. ## Why Use Domain Vocabulary? Professional contexts require precise terminology that often differs from general language usage. Here's why explicit vocabulary definitions matter: - **Prevent Misinterpretation**: terms like "deployment" mean different things in military, software, and business contexts - **Multilingual Consistency**: ensure accurate understanding across languages and regional variants - **Professional Standards**: align AI communication with industry-specific terminology conventions - **Context Boundaries**: establish clear domain-specific definitions to prevent confusion ## The Problem with General Language Understanding AI models are trained on general internet text, which means they understand common usage but may miss nuanced professional meanings. For example: - "sprint" could mean athletics, agile development, or telecom services - "pipeline" varies between oil & gas, sales, data engineering, and CI/CD - "circuit breaker" has different meanings in electrical engineering versus software architecture `VocabularyTerm` solves this by providing explicit, contextual definitions that anchor the AI's understanding to your specific domain. ## Basic Usage: Single Terms Define individual vocabulary terms for your domain: ```{python} import talk_box as tb # Define a customer success term churn_term = tb.VocabularyTerm( term="Customer Churn", definition="The percentage of customers who stop using our service during a specific time period", synonyms=["attrition rate", "customer turnover", "subscription cancellation rate"] ) # Use in a prompt builder builder = ( tb.PromptBuilder() .persona("customer success manager") .vocabulary(churn_term) .task_context("Analyze customer retention patterns and improvement strategies") ) print(builder) ``` ## Working with Multiple Terms For comprehensive domain coverage, define multiple related terms: ```{python} tech_vocab = [ tb.VocabularyTerm( term="Escalation Path", definition="The structured process for transferring complex issues to specialized teams", synonyms=["escalation process", "tier advancement", "specialist referral"] ), tb.VocabularyTerm( term="Service Level Agreement", definition="Guaranteed response and resolution timeframes based on issue priority", synonyms=["SLA", "service guarantee", "response commitment"] ), tb.VocabularyTerm( term="Root Cause Analysis", definition="Systematic investigation to identify the underlying source of recurring issues", synonyms=["RCA", "deep dive analysis", "systematic troubleshooting"] ) ] builder = ( tb.PromptBuilder() .persona("technical support specialist") .vocabulary(tech_vocab) .task_context("Provide comprehensive technical support for enterprise software") ) print(builder) ``` ## Multilingual Support: Synonyms vs Translations `VocabularyTerm` supports two distinct approaches to multilingual terminology. **Language-coded synonyms** capture how users naturally refer to concepts in different languages, while **official translations** provide standardized terminology for formal communications. Use `synonyms=` with language codes when you want to recognize alternative expressions users might employ across languages: ```{python} recognition_term = tb.VocabularyTerm( term="Market Penetration Rate", definition="Percentage of target market currently using our services", synonyms=[ "market share", # English alternative "adoption rate", # Another English way "es:cuota de mercado", # How Spanish users might say it "de:Marktanteil", # How German users might refer to it "fr:part de marché" # How French users might express it ] ) ``` Use `translations=` when you need standardized terminology across languages for official communications: ```{python} standardization_term = tb.VocabularyTerm( term="Market Penetration Rate", definition="Percentage of target market currently using our services", synonyms=["market share", "adoption rate"], # English alternatives only translations={ "es": "Tasa de Penetración de Mercado", # Official Spanish name "de": "Marktdurchdringungsrate", # Official German name "fr": "Taux de Pénétration du Marché" # Official French name } ) ``` For comprehensive multilingual support, combine both approaches to handle both informal user expressions and formal terminology standards: ```{python} comprehensive_term = tb.VocabularyTerm( term="Customer Lifetime Value", definition="Total revenue expected from a customer relationship over time", synonyms=[ "CLV", "lifetime revenue", # English alternatives "es:valor del cliente", # Informal Spanish expression "de:Kundenwert" # Casual German way ], translations={ "es": "Valor de Vida del Cliente", # Official Spanish translation "de": "Kundenlebenszeitwert", # Official German translation "fr": "Valeur Vie Client" # Official French translation } ) ``` This dual approach ensures your AI assistant can both recognize how users naturally express concepts and respond using appropriate formal terminology for your organization's standards. ## Industry-Specific Examples ### Healthcare & Medical Informatics Healthcare systems require precise terminology for regulatory compliance and patient safety. Medical terms often have specific meanings that differ from general usage, and international healthcare organizations need standardized translations for interoperability. ```{python} healthcare_vocab = [ tb.VocabularyTerm( term="Electronic Health Record", definition="Digital version of patient medical history maintained by healthcare providers", synonyms=["EHR", "electronic medical record", "EMR", "digital health record"], translations={ "es": "Registro Médico Electrónico", "fr": "Dossier Médical Électronique", "de": "Elektronische Patientenakte" } ), tb.VocabularyTerm( term="Clinical Decision Support", definition="Health IT providing evidence-based treatment recommendations", synonyms=["CDS", "decision support system", "clinical guidance system"], translations={ "es": "Soporte de Decisiones Clínicas", "fr": "Aide à la Décision Clinique", "de": "Klinische Entscheidungsunterstützung" } ) ] health_bot = ( tb.ChatBot() .provider_model("anthropic:claude-sonnet-4-6") .system_prompt( tb.PromptBuilder() .persona("healthcare IT consultant", "medical informatics") .vocabulary(healthcare_vocab) .constraint("Maintain strict patient privacy and HIPAA compliance") ) ) ``` ### Software Development & DevOps Modern software architecture uses specialized patterns and practices that can be ambiguous without proper context. Terms like "circuit breaker" or "mesh" have specific technical meanings that differ significantly from their everyday usage. ```{python} devops_vocab = [ tb.VocabularyTerm( term="Blue-Green Deployment", definition="Deployment strategy using two identical environments to enable zero-downtime releases", synonyms=["blue green strategy", "dual environment deployment", "zero downtime deployment"] ), tb.VocabularyTerm( term="Circuit Breaker Pattern", definition="Resilience pattern that prevents cascading failures by monitoring service health", synonyms=["circuit breaker", "failure isolation pattern", "resilience pattern"] ), tb.VocabularyTerm( term="Service Mesh", definition="Infrastructure layer handling service-to-service communication in microservices", synonyms=["mesh architecture", "service communication layer", "microservices mesh"] ) ] devops_bot = ( tb.ChatBot() .provider_model("anthropic:claude-sonnet-4-6") .system_prompt( tb.PromptBuilder() .persona("DevOps architect", "cloud infrastructure and microservices") .vocabulary(devops_vocab) .task_context("Design resilient microservices architecture") ) ) ``` ### Financial Services Financial terminology requires precision for regulatory compliance and risk management. Many financial concepts have specific technical definitions that are critical for accurate analysis and reporting across global markets. ```{python} finance_vocab = [ tb.VocabularyTerm( term="Value at Risk", definition="Statistical measure of potential loss in portfolio value over specific time period", synonyms=["VaR", "risk measure", "portfolio risk metric"], translations={ "es": "Valor en Riesgo", "de": "Value-at-Risk", "fr": "Valeur en Risque" } ), tb.VocabularyTerm( term="Know Your Customer", definition="Regulatory requirement to verify client identities and assess risk profiles", synonyms=["KYC", "customer due diligence", "identity verification"], translations={ "es": "Conozca a Su Cliente", "de": "Kenne Deinen Kunden", "fr": "Connaître Son Client" } ) ] ``` ## Best Practices Creating effective vocabulary terms requires thoughtful consideration of how your team actually uses language in practice. These guidelines help ensure your vocabulary definitions are clear, maintainable, and provide maximum value for AI understanding within your specific domain context. ### 1. Use Clear, Operational Definitions Focus on how terms are used in your specific context rather than dictionary definitions: ```python # Good: Operational definition tb.VocabularyTerm( term="Sprint", definition="Two-week development cycle with defined scope and deliverables in agile methodology", synonyms=["iteration", "development cycle", "timebox"] ) # Avoid: Generic definition tb.VocabularyTerm( term="Sprint", definition="A short race run at full speed", synonyms=["dash", "run"] ) ``` ### 2. Include Common Abbreviations and Variants Capture the ways your team actually refers to concepts: ```{python} tb.VocabularyTerm( term="Application Programming Interface", definition="Set of protocols and tools for building software applications", synonyms=["API", "web service", "endpoint", "service interface"] ) ``` ### 3. Use Language Codes Properly Follow standard language codes (ISO 639-1/639-2) for consistent formatting: ```{python} # Standard language codes tb.VocabularyTerm( term="User Interface", definition="The visual elements and controls through which users interact with software.", synonyms=[ "UI", "interface", "frontend", "es:interfaz de usuario", # Spanish "fr:interface utilisateur", # French "de:Benutzeroberfläche", # German "pt-BR:interface do usuário" # Brazilian Portuguese ] ) ``` ### 4. Group Related Terms Organize vocabulary by domain or functional area for better maintainability: ```python # Authentication & Security Terms auth_vocab = [ tb.VocabularyTerm(term="Multi-Factor Authentication", ...), tb.VocabularyTerm(term="Single Sign-On", ...), tb.VocabularyTerm(term="Access Control", ...) ] # Database & Storage Terms data_vocab = [ tb.VocabularyTerm(term="ACID Compliance", ...), tb.VocabularyTerm(term="Eventual Consistency", ...), tb.VocabularyTerm(term="Sharding", ...) ] # Combine when needed all_vocab = auth_vocab + data_vocab ``` ## Integration with Other Features Vocabulary definitions work seamlessly with other Talk Box features to create comprehensive AI systems. When combined with conversation pathways, vocabulary ensures AI assistants understand domain-specific terminology while following structured dialogue flows: ```{python} # Define e-commerce vocabulary ecommerce_vocab = [ tb.VocabularyTerm( term="Cart Abandonment", definition="When customers add items to cart but don't complete purchase", synonyms=["abandoned cart", "incomplete checkout", "cart dropout"] ) ] # Create pathway with vocabulary context support_pathway = ( tb.Pathways("Customer Support", "systematic issue resolution") .state("understand the customer issue") .required(["problem description", "account information"]) .next_state("troubleshooting") ) support_bot = ( tb.ChatBot() .provider_model("anthropic:claude-sonnet-4-6") .system_prompt( tb.PromptBuilder() .persona("customer support specialist", "e-commerce platform") .vocabulary(ecommerce_vocab) .pathways(support_pathway) .constraint("Always maintain friendly, helpful tone") ) ) # Show the generated prompt print(support_bot.system_prompt) ``` Vocabulary becomes particularly valuable when analyzing domain-specific documents through file attachments, ensuring AI assistants correctly interpret specialized terminology in uploaded files: ```python legal_vocab = [ tb.VocabularyTerm( term="Force Majeure", definition="Unforeseeable circumstances preventing contract fulfillment", synonyms=["act of God", "unforeseeable event", "superior force"] ) ] contract_bot = ( tb.ChatBot() .provider_model("anthropic:claude-sonnet-4-6") .system_prompt( tb.PromptBuilder() .persona("legal analyst", "contract review") .vocabulary(legal_vocab) .task_context("Review contracts for key terms and potential issues") ) ) # Analyze contract with vocabulary context response = contract_bot.chat( "Please review this contract for key terms", attachments=["contract.pdf"] ) ``` ## Vocabulary Term Display When you print a `VocabularyTerm`, it displays in a clean, readable format: ```{python} term = tb.VocabularyTerm( term="Customer Lifetime Value", definition="Total revenue expected from a customer relationship over time", synonyms=["CLV", "lifetime revenue"], translations={"es": "Valor de Vida del Cliente"} ) print(term) ``` This formatting makes it easy to review and share vocabulary definitions with your team. ## Common Use Cases Domain vocabulary proves valuable across diverse organizational contexts. It's particularly effective for **onboarding new team members** with comprehensive terminology guides, enabling **cross-functional communication** where terms like "deployment" mean different things to DevOps versus Sales teams, and supporting **international operations** by ensuring consistent understanding across global teams working in different languages. The feature also excels in **regulatory compliance** scenarios where precise definitions matter legally, **customer support** contexts where AI assistants need to understand product-specific terminology, and **technical documentation** workflows where consistent definitions are critical for clarity and accuracy. ## Next Steps - **Explore [PromptBuilder Guide](prompt-builder.qmd)** for comprehensive prompt engineering - **Learn about [Conversation Pathways](pathways.qmd)** for structured dialogue management - **Check out [Testing & Validation](testing-avoid-topics.qmd)** for quality assurance Domain vocabulary is most powerful when combined with other Talk Box features to create comprehensive, professional AI systems that understand and communicate effectively within your specific business context.