Pattern-Based Topic Analysis Review and Options
Executive Summary
The orchestrator uses hardcoded pattern matching for topic extraction and continuity analysis in three methods:
_analyze_topic_continuity()- Hardcoded keyword matching (ML, AI, Data Science only)_extract_main_topic()- Hardcoded keyword matching (10+ topic categories)_extract_keywords()- Hardcoded important terms list
These methods are used extensively throughout the workflow, affecting reasoning chains, hypothesis generation, and agent execution tracking.
Current Implementation Analysis
1. _analyze_topic_continuity() (Lines 1026-1069)
Current Approach:
- Pattern matching against 3 hardcoded topics: "machine learning", "artificial intelligence", "data science"
- Checks session context summary and interaction context summaries for keywords
- Returns: "Continuing {topic} discussion" or "New topic: {topic}"
Limitations:
- Only recognizes 3 topics
- Misses domain-specific topics (e.g., healthcare, finance, legal)
- Misses nuanced topics (e.g., "transformer architectures" β classified as "general")
- Brittle: fails on synonyms, typos, or domain-specific terminology
- Not learning-enabled: requires manual updates for new domains
Usage:
- Reasoning chain step_1 evidence (line 187)
- Used once per request for context analysis
2. _extract_main_topic() (Lines 1251-1279)
Current Approach:
- Pattern matching against 10+ topic categories:
- AI chatbot course curriculum
- Programming course curriculum
- Educational course design
- Machine learning concepts
- Artificial intelligence and chatbots
- Data science and analysis
- Software development and programming
- General inquiry (fallback)
Limitations:
- Hardcoded keyword lists
- Hierarchical but limited (e.g., curriculum β AI vs Programming)
- Fallback to first 4 words if no match
- Same brittleness as topic continuity
Usage:
- Extensively used (18 times):
- Reasoning chain step_1 hypothesis (line 182)
- Reasoning chain step_1 reasoning (line 191)
- Reasoning chain step_2 reasoning (skills) (line 238)
- Reasoning chain step_3 hypothesis (line 243)
- Reasoning chain step_3 reasoning (line 251)
- Reasoning chain step_4 hypothesis (line 260)
- Reasoning chain step_4 reasoning (line 268)
- Reasoning chain step_5 hypothesis (line 296)
- Reasoning chain step_5 reasoning (line 304)
- Reasoning chain step_6 hypothesis (line 376)
- Reasoning chain step_6 reasoning (line 384)
- Alternative reasoning paths (line 1110)
- Error recovery (line 1665)
3. _extract_keywords() (Lines 1281-1295)
Current Approach:
- Extracts keywords from hardcoded important terms list
- Returns comma-separated string of matched keywords
Limitations:
- Static list requires manual updates
- May miss domain-specific terminology
Usage:
- Reasoning chain step_1 evidence (line 188)
- Used once per request
Current Workflow Impact
Pattern Matching Usage Flow:
Request β Context Retrieval
β
Reasoning Chain Step 1:
- Hypothesis: Uses _extract_main_topic() β "User is asking about: '{topic}'"
- Evidence: Uses _analyze_topic_continuity() β "Topic continuity: ..."
- Evidence: Uses _extract_keywords() β "Query keywords: ..."
- Reasoning: Uses _extract_main_topic() β "...focused on {topic}..."
β
Intent Recognition (Agent executes independently)
β
Reasoning Chain Step 2-6:
- All hypothesis/reasoning strings use _extract_main_topic()
- Topic appears in 12+ reasoning chain fields
β
Alternative Reasoning Paths:
- Uses _extract_main_topic() for path generation
β
Error Recovery:
- Uses _extract_main_topic() for error context
Impact Points:
- Reasoning Chain Documentation: All reasoning chain steps include topic strings
- Agent Execution Tracking: Topic appears in hypothesis and reasoning fields
- Error Recovery: Uses topic for context in error scenarios
- Logging/Debugging: Topic strings appear in logs and execution traces
Important Note: Pattern matching does NOT affect agent execution logic. Agents (Intent, Skills, Synthesis, Safety) execute independently using LLM inference. Pattern matching only affects:
- Reasoning chain metadata (for debugging/analysis)
- Logging messages
- Hypothesis/reasoning strings in execution traces
Options for Resolution
Option 1: Remove Pattern Matching, Make Context Independent
Approach:
- Remove
_analyze_topic_continuity(),_extract_main_topic(),_extract_keywords() - Replace with generic placeholders or remove from reasoning chains
- Use actual context data (session_context, interaction_contexts, user_context) directly
Implementation Changes:
Replace topic extraction with context-based strings:
# Before: hypothesis = f"User is asking about: '{self._extract_main_topic(user_input)}'" # After: hypothesis = f"User query analyzed with {len(interaction_contexts)} previous contexts"Replace topic continuity with context-based analysis:
# Before: f"Topic continuity: {self._analyze_topic_continuity(context, user_input)}" # After: f"Session context available: {bool(session_context)}" f"Interaction contexts: {len(interaction_contexts)}"Replace keywords with user input excerpt:
# Before: f"Query keywords: {self._extract_keywords(user_input)}" # After: f"Query: {user_input[:100]}..."
Impact Analysis:
β Benefits:
- No hardcoded patterns: Context independent of pattern learning
- Simpler code: Removes 100+ lines of pattern matching logic
- More accurate: Uses actual context data instead of brittle keyword matching
- Domain agnostic: Works for any topic/domain without updates
- Maintainability: No need to update keyword lists for new domains
- Performance: No pattern matching overhead (minimal, but measurable)
β Drawbacks:
- Less descriptive reasoning chains: Hypothesis strings less specific (e.g., "User query analyzed" vs "User is asking about: Machine learning concepts")
- Reduced human readability: Reasoning chain traces less informative for debugging
- Lost topic continuity insight: No explicit "continuing topic X" vs "new topic Y" distinction
Workflow Impact:
- No impact on agent execution: Agents already use LLM inference, not pattern matching
- Reasoning chains less informative: But still functional for debugging
- Logging less specific: But still captures context availability
- No breaking changes: All downstream components work with generic strings
Files Modified:
src/orchestrator_engine.py: Remove 3 methods, update 18+ usage sites
Estimated Effort: Low (1-2 hours) Risk Level: Low (only affects metadata, not logic)
Option 2: Use LLM API for Zero-Shot Classification
Approach:
- Replace pattern matching with LLM-based zero-shot topic classification
- Use LLM router to classify topics dynamically
- Cache results to minimize API calls
Implementation Changes:
- Create LLM-based topic extraction:
async def _extract_main_topic_llm(self, user_input: str, context: dict) -> str: """Extract topic using LLM zero-shot classification""" prompt = f"""Classify the main topic of this query in 2-5 words:
Query: "{user_input}"
Available context:
- Session summary: {context.get('session_context', {}).get('summary', 'N/A')[:200]}
- Recent interactions: {len(context.get('interaction_contexts', []))}
Respond with ONLY the topic name (e.g., "Machine Learning", "Healthcare Analytics", "Financial Modeling")."""
topic = await self.llm_router.route_inference(
task_type="classification",
prompt=prompt,
max_tokens=20,
temperature=0.3
)
return topic.strip() if topic else "General inquiry"
2. **Create LLM-based topic continuity:**
```python
async def _analyze_topic_continuity_llm(self, context: dict, user_input: str) -> str:
"""Analyze topic continuity using LLM"""
session_context = context.get('session_context', {}).get('summary', '')
recent_interactions = context.get('interaction_contexts', [])[:3]
prompt = f"""Determine if the current query continues the previous conversation topic or introduces a new topic.
Session Summary: {session_context[:300]}
Recent Interactions:
{chr(10).join([ic.get('summary', '') for ic in recent_interactions])}
Current Query: "{user_input}"
Respond with one of:
- "Continuing [topic] discussion" if same topic
- "New topic: [topic]" if different topic
Keep response under 50 words."""
continuity = await self.llm_router.route_inference(
task_type="general_reasoning",
prompt=prompt,
max_tokens=50,
temperature=0.5
)
return continuity.strip() if continuity else "No previous context"
Update method signatures to async:
_extract_main_topic()βasync def _extract_main_topic_llm()_analyze_topic_continuity()βasync def _analyze_topic_continuity_llm()_extract_keywords()β Keep pattern-based or remove (keywords less critical)
Add caching:
# Cache topic extraction per user_input (hash) topic_cache = {} input_hash = hashlib.md5(user_input.encode()).hexdigest() if input_hash in topic_cache: return topic_cache[input_hash] topic = await _extract_main_topic_llm(...) topic_cache[input_hash] = topic return topic
Impact Analysis:
β Benefits:
- Accurate topic classification: LLM understands context, synonyms, nuances
- Domain adaptive: Works for any domain without code changes
- Context-aware: Uses session_context and interaction_contexts for continuity
- Human-readable: Maintains descriptive reasoning chain strings
- Scalable: No manual keyword list maintenance
β Drawbacks:
- API latency: Adds 2-3 LLM calls per request (~200-500ms total)
- API costs: Additional tokens consumed per request
- Dependency on LLM availability: Requires LLM router to be functional
- Complexity: More code to maintain (async handling, caching, error handling)
- Inconsistency risk: LLM responses may vary slightly between calls (though temperature=0.3 mitigates)
Workflow Impact:
Positive:
- More accurate reasoning chains: Topic classification more reliable
- Better debugging: More informative hypothesis/reasoning strings
- Context-aware continuity: Uses actual session/interaction contexts
Negative:
- Latency increase: +200-500ms per request (2-3 LLM calls)
- Error handling complexity: Need fallbacks if LLM calls fail
- Async complexity: All 18+ usage sites need await statements
Implementation Complexity:
- Method conversion: 3 methods β async LLM calls
- Usage site updates: 18+ sites need await/async propagation
- Caching infrastructure: Add cache layer to reduce API calls
- Error handling: Fallbacks if LLM unavailable
- Testing: Verify LLM responses are reasonable
Files Modified:
src/orchestrator_engine.py: Rewrite 3 methods, update 18+ usage sites with async/await- May need
process_request()refactoring for async topic extraction
Estimated Effort: Medium-High (4-6 hours) Risk Level: Medium (adds latency and LLM dependency)
Recommendation
Recommended: Option 1 (Remove Pattern Matching)
Rationale:
- No impact on core functionality: Pattern matching only affects metadata strings, not agent execution
- Simpler implementation: Low risk, fast to implement
- No performance penalty: Removes overhead instead of adding LLM calls
- Maintainability: Less code to maintain
- Context independence: Aligns with user requirement for pattern-independent context
If descriptive reasoning chains are critical:
- Hybrid Approach: Use Option 1 for production, but add optional LLM-based topic extraction as a debug/logging enhancement (non-blocking, optional)
Alternative: Option 2 (LLM Classification) if reasoning chain quality is critical
Use Case:
- If reasoning chain metadata is used for:
- User-facing explanations
- Advanced debugging/analysis tools
- External integrations requiring topic metadata
- Then the latency/API cost may be justified
Migration Path
Option 1 Implementation Steps:
Remove methods:
- Delete
_analyze_topic_continuity()(lines 1026-1069) - Delete
_extract_main_topic()(lines 1251-1279) - Delete
_extract_keywords()(lines 1281-1295)
- Delete
Replace usages:
- Line 182:
hypothesisβ Use generic: "User query analysis" - Line 187:
Topic continuityβ Use: "Session context available: {bool(session_context)}" - Line 188:
Query keywordsβ Use: "Query: {user_input[:100]}" - Line 191:
reasoningβ Remove topic references - Lines 238, 243, 251, 260, 268, 296, 304, 376, 384: Remove topic from reasoning strings
- Line 1110: Remove topic from alternative paths
- Line 1665: Use generic error context
- Line 182:
Test:
- Verify reasoning chains still populate correctly
- Verify no syntax errors
- Verify agents execute normally
Option 2 Implementation Steps:
- Create async LLM methods (as shown above)
- Add caching layer
- Update
process_request()to await topic extraction before reasoning chain - Add error handling with fallbacks
- Test latency impact
- Monitor API usage
Conclusion
Option 1 is recommended for immediate implementation due to:
- Low risk and complexity
- No performance penalty
- Aligns with context independence requirement
- Pattern matching doesn't affect agent execution
Option 2 should be considered only if reasoning chain metadata quality is critical for user-facing features or advanced debugging.