JatsTheAIGen commited on
Commit
f89bd21
·
1 Parent(s): cb5e65b

cache key error when user id changes -fixed task 1 31_10_2025 v5

Browse files
APPLICATION_FEATURES_REPORT.md ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Research AI Assistant: Key Features Report
2
+
3
+ ## Executive Summary
4
+
5
+ This application implements a **multi-agent orchestration system** for research assistance with transparent reasoning chains, context-aware conversation management, and adaptive expert consultation assignment. The system employs **task-based LLM routing**, **hierarchical context summarization**, and **non-blocking safety validation** to deliver contextually relevant, academically rigorous responses.
6
+
7
+ ---
8
+
9
+ ## 1. Multi-Agent Orchestration Architecture
10
+
11
+ ### 1.1 Central Orchestration Engine (`MVPOrchestrator`)
12
+ - **Sequential workflow coordination**: Manages a deterministic pipeline of specialized agents
13
+ - **Execution trace logging**: Maintains comprehensive audit trails of agent execution
14
+ - **Graceful degradation**: Implements fallback mechanisms at every processing stage
15
+ - **Reasoning chain generation**: Constructs explicit chain-of-thought (CoT) reasoning structures with:
16
+ - Hypothesis formation
17
+ - Evidence collection
18
+ - Confidence calibration
19
+ - Alternative path analysis
20
+ - Uncertainty identification
21
+
22
+ ### 1.2 Specialized Agent Modules
23
+
24
+ #### Intent Recognition Agent (`IntentRecognitionAgent`)
25
+ - **Multi-class intent classification**: Categorizes user queries into 8 intent types:
26
+ - Information requests
27
+ - Task execution
28
+ - Creative generation
29
+ - Analysis/research
30
+ - Casual conversation
31
+ - Troubleshooting
32
+ - Education/learning
33
+ - Technical support
34
+ - **Dual-mode operation**: LLM-enhanced classification with rule-based fallback
35
+ - **Confidence calibration**: Multi-factor confidence scoring with context enhancement
36
+ - **Secondary intent detection**: Identifies complementary intent interpretations
37
+
38
+ #### Skills Identification Agent (`SkillsIdentificationAgent`)
39
+ - **Market analysis integration**: Leverages 9 industry categories with market share data
40
+ - **Dual-stage processing**:
41
+ 1. Market relevance analysis (reasoning_primary model)
42
+ 2. Skill classification (classification_specialist model)
43
+ - **Probability-based skill mapping**: Identifies expert skills with ≥20% relevance threshold
44
+ - **Expert consultant assignment**: Feeds skill probabilities to synthesis agent for consultant profile selection
45
+
46
+ #### Response Synthesis Agent (`SynthesisAgent`)
47
+ - **Expert consultant integration**: Dynamically assigns ultra-expert profiles based on identified skills
48
+ - **Multi-source synthesis**: Integrates outputs from multiple specialized agents
49
+ - **Weighted expertise combination**: Creates composite consultant profiles from relevant skill domains
50
+ - **Coherence scoring**: Evaluates response quality and structure
51
+
52
+ #### Safety Check Agent (`SafetyCheckAgent`)
53
+ - **Non-blocking safety validation**: Appends advisory warnings without content modification
54
+ - **Multi-dimensional analysis**: Evaluates toxicity, bias, privacy, and controversial content
55
+ - **Threshold-based warnings**: Generates contextual warnings when safety scores exceed thresholds
56
+ - **Pattern-based fallback**: Rule-based detection when LLM analysis unavailable
57
+
58
+ ---
59
+
60
+ ## 2. Context Management System
61
+
62
+ ### 2.1 Hierarchical Context Architecture
63
+ The system implements a **three-tier context summarization** strategy:
64
+
65
+ #### Tier 1: User Context (500 tokens)
66
+ - **Persistent persona summaries**: Cross-session user profiles generated from historical interactions
67
+ - **Lifespan**: Persists across all sessions for a given user_id
68
+ - **Generation trigger**: Automatically generated when user has sufficient interaction history
69
+ - **Content**: Communication style, topic preferences, interaction patterns
70
+
71
+ #### Tier 2: Session Context (100 tokens)
72
+ - **Session-level summaries**: Summarizes all interactions within a single session
73
+ - **Generation trigger**: Generated at session end
74
+ - **Storage**: Stored in `session_contexts` table linked to user_id
75
+
76
+ #### Tier 3: Interaction Context (50 tokens)
77
+ - **Per-interaction summaries**: Compact summaries of individual exchanges
78
+ - **Generation trigger**: Generated after each response
79
+ - **Storage**: Stored in `interaction_contexts` table
80
+ - **Retrieval**: Last 20 interaction contexts loaded per session
81
+
82
+ ### 2.2 Context Optimization Features
83
+ - **Multi-level caching**: In-memory session cache + SQLite persistence
84
+ - **Transaction-based updates**: Atomic database operations with write-ahead logging (WAL)
85
+ - **Deduplication**: SHA-256 hash-based duplicate interaction prevention
86
+ - **Cache invalidation**: Automatic cache clearing on user_id changes
87
+ - **Database indexing**: Optimized queries with indexes on session_id, user_id, timestamps
88
+
89
+ ### 2.3 Context Delivery Format
90
+ Context delivered to agents in structured format:
91
+ ```
92
+ [User Context]
93
+ [User persona summary - 500 tokens]
94
+
95
+ [Interaction Context #N]
96
+ [Most recent interaction summary - 50 tokens]
97
+
98
+ [Interaction Context #N-1]
99
+ [Previous interaction summary - 50 tokens]
100
+ ...
101
+ ```
102
+
103
+ ---
104
+
105
+ ## 3. LLM Routing System
106
+
107
+ ### 3.1 Task-Based Model Routing (`LLMRouter`)
108
+ Implements **intelligent model selection** based on task specialization:
109
+
110
+ | Task Type | Model Assignment | Purpose |
111
+ |-----------|-----------------|---------|
112
+ | `intent_classification` | `classification_specialist` | Fast intent categorization |
113
+ | `embedding_generation` | `embedding_specialist` | Semantic similarity (currently unused) |
114
+ | `safety_check` | `safety_checker` | Content moderation |
115
+ | `general_reasoning` | `reasoning_primary` | Primary response generation |
116
+ | `response_synthesis` | `reasoning_primary` | Multi-source synthesis |
117
+
118
+ ### 3.2 Model Configuration (`LLM_CONFIG`)
119
+ - **Primary model**: `Qwen/Qwen2.5-7B-Instruct` (chat completions API)
120
+ - **Fallback chain**: Primary → Fallback → Degraded mode
121
+ - **Health checking**: Model availability monitoring with automatic fallback
122
+ - **Retry logic**: Exponential backoff (1s → 16s max) with 3 retry attempts
123
+ - **API protocol**: Hugging Face Chat Completions API (`router.huggingface.co/v1/chat/completions`)
124
+
125
+ ### 3.3 Performance Optimizations
126
+ - **Timeout management**: 30-second request timeout
127
+ - **Connection pooling**: Reusable HTTP connections
128
+ - **Request/response logging**: Comprehensive logging of all LLM API interactions
129
+
130
+ ---
131
+
132
+ ## 4. Reasoning and Transparency
133
+
134
+ ### 4.1 Chain-of-Thought Reasoning
135
+ The orchestrator generates **explicit reasoning chains** for each request:
136
+
137
+ ```python
138
+ reasoning_chain = {
139
+ "chain_of_thought": {
140
+ "step_1": {
141
+ "hypothesis": "User intent analysis",
142
+ "evidence": [...],
143
+ "confidence": 0.85,
144
+ "reasoning": "..."
145
+ },
146
+ "step_2": {...},
147
+ ...
148
+ },
149
+ "alternative_paths": [...],
150
+ "uncertainty_areas": [...],
151
+ "evidence_sources": [...],
152
+ "confidence_calibration": {...}
153
+ }
154
+ ```
155
+
156
+ ### 4.2 Reasoning Components
157
+ - **Hypothesis formation**: Explicit hypothesis statements at each processing step
158
+ - **Evidence collection**: Structured evidence arrays supporting each hypothesis
159
+ - **Confidence calibration**: Weighted confidence scoring across reasoning steps
160
+ - **Alternative path analysis**: Consideration of alternative interpretation paths
161
+ - **Uncertainty identification**: Explicit documentation of low-confidence areas
162
+
163
+ ### 4.3 Metadata Generation
164
+ Every response includes:
165
+ - **Agent execution trace**: Complete log of agents executed
166
+ - **Processing time**: Performance metrics
167
+ - **Token count**: Resource usage tracking
168
+ - **Confidence scores**: Overall confidence in response quality
169
+ - **Skills identification**: Relevant expert skills for the query
170
+
171
+ ---
172
+
173
+ ## 5. Expert Consultant Assignment
174
+
175
+ ### 5.1 Dynamic Consultant Selection
176
+ The synthesis agent employs **ExpertConsultantAssigner** to create composite consultant profiles:
177
+
178
+ - **10 predefined expert profiles**: Data analysis, technical programming, project management, financial analysis, digital marketing, business consulting, cybersecurity, healthcare technology, educational technology, environmental science
179
+ - **Weighted expertise combination**: Creates "ultra-expert" profiles by combining relevant consultants based on skill probabilities
180
+ - **Experience aggregation**: Sums years of experience across combined experts
181
+ - **Style integration**: Merges consulting styles from multiple domains
182
+
183
+ ### 5.2 Market Analysis Integration
184
+ - **9 industry categories** with market share and growth rate data
185
+ - **Specialized skill mapping**: 3-7 specialized skills per category
186
+ - **Relevance scoring**: Skills ranked by relevance to user query
187
+ - **Market context**: Response synthesis informed by industry trends
188
+
189
+ ---
190
+
191
+ ## 6. Safety and Bias Mitigation
192
+
193
+ ### 6.1 Non-Blocking Safety System
194
+ - **Warning-based approach**: Appends safety advisories without blocking content
195
+ - **Multi-dimensional analysis**: Evaluates toxicity, bias, privacy, controversial content
196
+ - **Intent-aware thresholds**: Different thresholds per intent category
197
+ - **Automatic warning injection**: Safety warnings automatically appended when thresholds exceeded
198
+
199
+ ### 6.2 Safety Thresholds
200
+ ```python
201
+ safety_thresholds = {
202
+ "toxicity_or_harmful_language": 0.3,
203
+ "potential_biases_or_stereotypes": 0.05, # Low threshold for bias
204
+ "privacy_or_security_concerns": 0.2,
205
+ "controversial_or_sensitive_topics": 0.3
206
+ }
207
+ ```
208
+
209
+ ### 6.3 User Choice Feature (Paused)
210
+ - **Design**: Originally designed to prompt user for revision approval
211
+ - **Current implementation**: Warnings automatically appended to responses
212
+ - **No blocking**: All responses delivered regardless of safety scores
213
+
214
+ ---
215
+
216
+ ## 7. User Interface
217
+
218
+ ### 7.1 Mobile-First Design
219
+ - **Responsive layout**: Adaptive UI for mobile, tablet, desktop
220
+ - **Touch-optimized**: 44px minimum touch targets (iOS/Android guidelines)
221
+ - **Font sizing**: 16px minimum to prevent mobile browser zoom
222
+ - **Viewport management**: 60vh chat container with optimized scrolling
223
+
224
+ ### 7.2 UI Components
225
+ - **Chat interface**: Gradio chatbot with message history
226
+ - **Skills display**: Visual tags showing identified expert skills with confidence indicators
227
+ - **Details tab**: Collapsible accordions showing:
228
+ - Reasoning chain (JSON)
229
+ - Agent performance metrics
230
+ - Session context data
231
+ - **Session management**: User selection dropdown, session ID display, new session button
232
+
233
+ ### 7.3 Progressive Web App Features
234
+ - **Offline capability**: Cached session data
235
+ - **Dark mode support**: CSS media queries for system preference
236
+ - **Accessibility**: Screen reader compatible, keyboard navigation
237
+
238
+ ---
239
+
240
+ ## 8. Database Architecture
241
+
242
+ ### 8.1 Schema Design
243
+ **Tables:**
244
+ 1. `sessions`: Session metadata, context data, user_id tracking
245
+ 2. `interactions`: Individual interaction records with context snapshots
246
+ 3. `user_contexts`: Persistent user persona summaries (500 tokens)
247
+ 4. `session_contexts`: Session-level summaries (100 tokens)
248
+ 5. `interaction_contexts`: Individual interaction summaries (50 tokens)
249
+ 6. `user_change_log`: Audit log of user_id changes
250
+
251
+ ### 8.2 Data Integrity Features
252
+ - **Transaction management**: Atomic operations with rollback on failure
253
+ - **Foreign key constraints**: Referential integrity enforcement
254
+ - **Deduplication**: SHA-256 hash-based unique interaction tracking
255
+ - **Indexing**: Optimized indexes on frequently queried columns
256
+
257
+ ### 8.3 Concurrency Management
258
+ - **Thread-safe transactions**: RLock-based locking for concurrent access
259
+ - **Write-Ahead Logging (WAL)**: SQLite WAL mode for better concurrency
260
+ - **Busy timeout**: 5-second timeout for lock acquisition
261
+ - **Connection pooling**: Efficient database connection reuse
262
+
263
+ ---
264
+
265
+ ## 9. Performance Optimizations
266
+
267
+ ### 9.1 Caching Strategy
268
+ - **Multi-level caching**: In-memory session cache + persistent SQLite storage
269
+ - **Cache TTL**: 1-hour time-to-live for session cache
270
+ - **LRU eviction**: Least-recently-used eviction policy
271
+ - **Cache warming**: Pre-loading frequently accessed sessions
272
+
273
+ ### 9.2 Request Processing
274
+ - **Async/await architecture**: Fully asynchronous agent execution
275
+ - **Parallel agent execution**: Concurrent execution when execution_plan specifies parallel order
276
+ - **Sequential fallback**: Sequential execution for dependency-sensitive tasks
277
+ - **Timeout protection**: 30-second timeout for safety revision loops
278
+
279
+ ### 9.3 Resource Management
280
+ - **Token budget management**: Configurable max_tokens per model
281
+ - **Session size limits**: 10MB per session maximum
282
+ - **Interaction history limits**: Last 40 interactions kept in memory, 20 loaded from database
283
+
284
+ ---
285
+
286
+ ## 10. Error Handling and Resilience
287
+
288
+ ### 10.1 Graceful Degradation
289
+ - **Multi-level fallbacks**: LLM → Rule-based → Default responses
290
+ - **Error isolation**: Agent failures don't cascade to system failure
291
+ - **Fallback responses**: Always returns user-facing response, never None
292
+ - **Comprehensive logging**: All errors logged with stack traces
293
+
294
+ ### 10.2 Loop Prevention
295
+ - **Safety response detection**: Prevents recursive safety checks on binary responses
296
+ - **Context retrieval caching**: 5-second cache prevents rapid successive context fetches
297
+ - **User change tracking**: Prevents context loops when user_id changes mid-session
298
+ - **Deduplication**: Prevents duplicate interaction processing
299
+
300
+ ---
301
+
302
+ ## 11. Academic Rigor Features
303
+
304
+ ### 11.1 Transparent Reasoning
305
+ - **Explicit CoT chains**: All reasoning steps documented
306
+ - **Evidence citation**: Structured evidence arrays for each hypothesis
307
+ - **Uncertainty quantification**: Explicit confidence scores and uncertainty areas
308
+ - **Alternative consideration**: Documented alternative interpretation paths
309
+
310
+ ### 11.2 Reproducibility
311
+ - **Execution traces**: Complete logs of agent execution order
312
+ - **Interaction IDs**: Unique identifiers for every interaction
313
+ - **Timestamp tracking**: Precise timestamps for all operations
314
+ - **Database audit trail**: Complete interaction history persisted
315
+
316
+ ### 11.3 Quality Metrics
317
+ - **Confidence calibration**: Weighted confidence scoring across steps
318
+ - **Coherence scoring**: Response quality evaluation
319
+ - **Processing time tracking**: Performance monitoring
320
+ - **Token usage tracking**: Resource consumption monitoring
321
+
322
+ ---
323
+
324
+ ## Technical Specifications
325
+
326
+ ### Dependencies
327
+ - **Gradio**: UI framework
328
+ - **SQLite**: Database persistence
329
+ - **Hugging Face API**: LLM inference
330
+ - **asyncio**: Asynchronous execution
331
+ - **Python 3.x**: Core runtime
332
+
333
+ ### Deployment
334
+ - **Platform**: Hugging Face Spaces (configurable)
335
+ - **Containerization**: Dockerfile support
336
+ - **GPU support**: Optional ZeroGPU allocation on HF Spaces
337
+ - **Environment**: Configurable via environment variables
338
+
339
+ ---
340
+
341
+ ## Summary
342
+
343
+ This application implements a **sophisticated multi-agent research assistance system** with the following distinguishing features:
344
+
345
+ 1. **Hierarchical context summarization** (50/100/500 token tiers)
346
+ 2. **Transparent reasoning chains** with explicit CoT documentation
347
+ 3. **Dynamic expert consultant assignment** based on skill identification
348
+ 4. **Non-blocking safety validation** with automatic warning injection
349
+ 5. **Task-based LLM routing** with intelligent fallback chains
350
+ 6. **Mobile-optimized interface** with PWA capabilities
351
+ 7. **Robust error handling** with graceful degradation at every layer
352
+ 8. **Academic rigor** through comprehensive metadata and audit trails
353
+
354
+ The system prioritizes **transparency**, **reliability**, and **contextual relevance** while maintaining **production-grade error handling** and **performance optimization**.
355
+
CONTEXT_PROVISION_ANALYSIS.md ADDED
@@ -0,0 +1,337 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Context Provision Analysis: Intent Agent Context Flow
2
+
3
+ ## Problem Statement
4
+
5
+ The Intent Recognition Agent (`src/agents/intent_agent.py`) expects a context dictionary with a `conversation_history` key, but the actual context structure provided by `EfficientContextManager` does not include this key. This results in `Available Context: []` being shown in the intent recognition prompt.
6
+
7
+ ## Context Flow Trace
8
+
9
+ ### Step 1: Orchestrator Retrieves Context
10
+
11
+ **Location**: `src/orchestrator_engine.py:172`
12
+
13
+ ```python
14
+ context = await self._get_or_create_context(session_id, user_input, user_id)
15
+ ```
16
+
17
+ This calls `context_manager.manage_context()` which returns a context dictionary.
18
+
19
+ ### Step 2: Context Structure Returned by Context Manager
20
+
21
+ **Location**: `src/context_manager.py:550-579` (`_optimize_context` method)
22
+
23
+ The context manager returns the following structure:
24
+
25
+ ```python
26
+ {
27
+ "session_id": str,
28
+ "user_id": str,
29
+ "user_context": str, # 500-token user persona summary
30
+ "interaction_contexts": [ # List of interaction summary dicts
31
+ {
32
+ "summary": str, # 50-token interaction summary
33
+ "timestamp": str
34
+ },
35
+ ...
36
+ ],
37
+ "combined_context": str, # Formatted string: "[User Context]\n...\n[Interaction Context #N]\n..."
38
+ "preferences": dict,
39
+ "active_tasks": list,
40
+ "last_activity": str
41
+ }
42
+ ```
43
+
44
+ ### Step 3: Intent Agent Receives Context
45
+
46
+ **Location**: `src/orchestrator_engine.py:201-203`
47
+
48
+ ```python
49
+ intent_result = await self.agents['intent_recognition'].execute(
50
+ user_input=user_input,
51
+ context=context
52
+ )
53
+ ```
54
+
55
+ ### Step 4: Intent Agent Attempts to Access Context
56
+
57
+ **Location**: `src/agents/intent_agent.py:109`
58
+
59
+ ```python
60
+ def _build_chain_of_thought_prompt(self, user_input: str, context: Dict[str, Any]) -> str:
61
+ return f"""
62
+ Analyze the user's intent step by step:
63
+
64
+ User Input: "{user_input}"
65
+
66
+ Available Context: {context.get('conversation_history', [])[-2:] if context else []}
67
+ ...
68
+ """
69
+ ```
70
+
71
+ **Issue**: The code attempts to access `context.get('conversation_history', [])`, but the context dictionary **does not contain this key**.
72
+
73
+ ## Root Cause Analysis
74
+
75
+ ### Expected Context Structure (by Intent Agent)
76
+ The intent agent expects:
77
+ ```python
78
+ context = {
79
+ 'conversation_history': [
80
+ {...}, # Previous conversation turn
81
+ {...}, # Another previous turn
82
+ ...
83
+ ]
84
+ }
85
+ ```
86
+
87
+ ### Actual Context Structure (from Context Manager)
88
+ The context manager provides:
89
+ ```python
90
+ context = {
91
+ 'interaction_contexts': [
92
+ {'summary': '...', 'timestamp': '...'},
93
+ {'summary': '...', 'timestamp': '...'},
94
+ ...
95
+ ],
96
+ 'user_context': '...',
97
+ 'combined_context': '...',
98
+ ...
99
+ }
100
+ ```
101
+
102
+ ### Why This Mismatch Exists
103
+
104
+ 1. **Historical Evolution**: The intent agent was likely designed with an earlier context structure in mind
105
+ 2. **Context Manager Redesign**: The context manager was redesigned to use hierarchical summarization (50/100/500 token tiers) instead of full conversation history
106
+ 3. **Missing Adaptation**: The intent agent was not updated to use the new context structure
107
+
108
+ ## Impact Analysis
109
+
110
+ ### First Turn (No Previous Context)
111
+ - `interaction_contexts` = `[]` (empty list)
112
+ - `user_context` = `""` (empty string if first-time user)
113
+ - **Result**: `Available Context: []` ✓ (Correct, but for wrong reason - key doesn't exist)
114
+
115
+ ### Second Turn (After First Interaction)
116
+ - `interaction_contexts` = `[{summary: "...", timestamp: "..."}]` (1 interaction)
117
+ - `user_context` = `""` or persona summary if user has history
118
+ - **Result**: `Available Context: []` ✗ (Incorrect - context exists but wrong key accessed)
119
+
120
+ ### Third Turn and Beyond
121
+ - `interaction_contexts` = `[{...}, {...}, ...]` (multiple interactions)
122
+ - `user_context` = Persona summary (if user has sufficient history)
123
+ - **Result**: `Available Context: []` ✗ (Incorrect - rich context exists but not accessible)
124
+
125
+ ## Context Accumulation Over Multiple Turns
126
+
127
+ ### Turn 1: User says "What is machine learning?"
128
+ 1. Context Manager retrieves context:
129
+ - `interaction_contexts`: `[]` (no previous interactions)
130
+ - `user_context`: `""` (first-time user, no persona yet)
131
+ - Context passed to intent agent
132
+
133
+ 2. Intent Agent builds prompt:
134
+ - `context.get('conversation_history', [])[-2:]` → `[]`
135
+ - **Shows**: `Available Context: []`
136
+
137
+ 3. After response, interaction context generated:
138
+ - `generate_interaction_context()` called
139
+ - Creates 50-token summary: "User asked about machine learning definition"
140
+ - Stored in `interaction_contexts` table
141
+
142
+ ### Turn 2: User says "How does it differ from deep learning?"
143
+ 1. Context Manager retrieves context:
144
+ - `interaction_contexts`: `[{summary: "User asked about machine learning definition", timestamp: "..."}]`
145
+ - `user_context`: Still `""` (not enough history for persona)
146
+ - Context passed to intent agent
147
+
148
+ 2. Intent Agent builds prompt:
149
+ - `context.get('conversation_history', [])[-2:]` → `[]` (key doesn't exist!)
150
+ - **Shows**: `Available Context: []` ✗ **SHOULD show the interaction summary**
151
+
152
+ 3. After response, another interaction context generated:
153
+ - Creates: "User asked about differences between machine learning and deep learning"
154
+ - Stored in `interaction_contexts` table
155
+ - Now has 2 interaction contexts
156
+
157
+ ### Turn 3: User says "Can you explain neural networks?"
158
+ 1. Context Manager retrieves context:
159
+ - `interaction_contexts`: `[{summary: "...deep learning..."}, {summary: "...machine learning..."}]`
160
+ - `user_context`: Still `""` (persona generated only after sufficient history)
161
+ - Context passed to intent agent
162
+
163
+ 2. Intent Agent builds prompt:
164
+ - `context.get('conversation_history', [])[-2:]` → `[]` (key doesn't exist!)
165
+ - **Shows**: `Available Context: []` ✗ **SHOULD show 2 interaction summaries**
166
+
167
+ ### After ~20-50 Interactions (User Persona Generation)
168
+ 1. Context Manager retrieves context:
169
+ - `interaction_contexts`: `[{...}, {...}, ...]` (up to 20 most recent)
170
+ - `user_context`: `"User persona: Interested in AI topics, asks technical questions..."` (500-token summary)
171
+ - Context passed to intent agent
172
+
173
+ 2. Intent Agent builds prompt:
174
+ - `context.get('conversation_history', [])[-2:]` → `[]` (key doesn't exist!)
175
+ - **Shows**: `Available Context: []` ✗ **SHOULD show rich context including user persona and interaction history**
176
+
177
+ ## Available Context Data (Not Being Used)
178
+
179
+ ### What Context Actually Contains
180
+
181
+ #### Turn 1:
182
+ ```python
183
+ context = {
184
+ "interaction_contexts": [], # Empty - first turn
185
+ "user_context": "", # Empty - first-time user
186
+ "combined_context": "", # Empty
187
+ }
188
+ ```
189
+
190
+ #### Turn 2:
191
+ ```python
192
+ context = {
193
+ "interaction_contexts": [
194
+ {"summary": "User asked about machine learning definition", "timestamp": "..."}
195
+ ],
196
+ "user_context": "", # Still empty
197
+ "combined_context": "[Interaction Context #1]\nUser asked about machine learning definition",
198
+ }
199
+ ```
200
+
201
+ #### Turn 3+:
202
+ ```python
203
+ context = {
204
+ "interaction_contexts": [
205
+ {"summary": "User asked about differences between ML and DL", "timestamp": "..."},
206
+ {"summary": "User asked about machine learning definition", "timestamp": "..."},
207
+ # ... more interactions
208
+ ],
209
+ "user_context": "User persona: Interested in AI topics...", # If sufficient history
210
+ "combined_context": "[User Context]\nUser persona...\n\n[Interaction Context #2]\n...\n\n[Interaction Context #1]\n...",
211
+ }
212
+ ```
213
+
214
+ ## Recommended Solutions
215
+
216
+ ### Option 1: Use `interaction_contexts` Directly (Minimal Change)
217
+
218
+ **Modify**: `src/agents/intent_agent.py:109`
219
+
220
+ ```python
221
+ # OLD:
222
+ Available Context: {context.get('conversation_history', [])[-2:] if context else []}
223
+
224
+ # NEW:
225
+ Available Context: {[ic.get('summary', '') for ic in context.get('interaction_contexts', [])[-2:]] if context else []}
226
+ ```
227
+
228
+ **Pros**:
229
+ - Minimal code change
230
+ - Uses actual context data
231
+ - Shows last 2 interaction summaries
232
+
233
+ **Cons**:
234
+ - Only shows summaries, not full conversation
235
+ - Loses timestamp information
236
+
237
+ ### Option 2: Use `combined_context` (Preferred)
238
+
239
+ **Modify**: `src/agents/intent_agent.py:109`
240
+
241
+ ```python
242
+ # OLD:
243
+ Available Context: {context.get('conversation_history', [])[-2:] if context else []}
244
+
245
+ # NEW:
246
+ Available Context: {context.get('combined_context', 'No previous context available') if context else 'No context available'}
247
+ ```
248
+
249
+ **Pros**:
250
+ - Uses pre-formatted context string
251
+ - Includes both user context and interaction contexts
252
+ - More informative for intent recognition
253
+ - Better reflects the hierarchical context system
254
+
255
+ **Cons**:
256
+ - May include more than just last 2 turns (includes up to 10 interactions)
257
+ - Longer context string
258
+
259
+ ### Option 3: Build Conversation History from Interaction Contexts (Most Flexible)
260
+
261
+ **Modify**: `src/agents/intent_agent.py:101-118`
262
+
263
+ ```python
264
+ def _build_chain_of_thought_prompt(self, user_input: str, context: Dict[str, Any]) -> str:
265
+ """Build Chain of Thought prompt for intent recognition"""
266
+
267
+ # Extract conversation history from interaction_contexts
268
+ conversation_history = []
269
+ if context:
270
+ interaction_contexts = context.get('interaction_contexts', [])
271
+ # Get last 2 interaction summaries for context
272
+ for ic in interaction_contexts[-2:]:
273
+ conversation_history.append({
274
+ 'summary': ic.get('summary', ''),
275
+ 'timestamp': ic.get('timestamp', '')
276
+ })
277
+
278
+ # Optionally include user context
279
+ user_context_summary = ""
280
+ if context and context.get('user_context'):
281
+ user_context_summary = f"\nUser Context: {context.get('user_context')[:200]}..." # Truncate for brevity
282
+
283
+ return f"""
284
+ Analyze the user's intent step by step:
285
+
286
+ User Input: "{user_input}"
287
+
288
+ Previous Context: {conversation_history if conversation_history else 'No previous interactions'}
289
+ {user_context_summary}
290
+
291
+ Step 1: Identify key entities, actions, and questions in the input
292
+ Step 2: Map to intent categories: {', '.join(self.intent_categories)}
293
+ Step 3: Consider the conversation flow and user's likely goals
294
+ Step 4: Assign confidence scores (0.0-1.0) for each relevant intent
295
+ Step 5: Provide reasoning for the classification
296
+
297
+ Respond with JSON format containing primary_intent, secondary_intents, confidence_scores, and reasoning_chain.
298
+ """
299
+ ```
300
+
301
+ **Pros**:
302
+ - Flexible format
303
+ - Can include both interaction history and user context
304
+ - Properly handles empty context
305
+ - More informative for LLM
306
+
307
+ **Cons**:
308
+ - More code changes
309
+ - Slightly more complex
310
+
311
+ ## Current Behavior Summary
312
+
313
+ | Turn | Interaction Contexts Available | User Context Available | Intent Agent Sees |
314
+ |------|-------------------------------|----------------------|-------------------|
315
+ | 1 | 0 | No | `[]` (empty) |
316
+ | 2 | 1 | No | `[]` (empty) ✗ |
317
+ | 3 | 2 | Possibly | `[]` (empty) ✗ |
318
+ | 10+ | 10-20 | Yes (if sufficient history) | `[]` (empty) ✗ |
319
+
320
+ **Key Issue**: Intent agent never sees the available context data because it looks for the wrong key (`conversation_history` instead of `interaction_contexts` or `combined_context`).
321
+
322
+ ## Testing Recommendations
323
+
324
+ 1. **Verify Context Structure**: Log the actual context dict passed to intent agent
325
+ 2. **Test Multiple Turns**: Verify context accumulates correctly over multiple interactions
326
+ 3. **Test Persona Generation**: Verify user_context appears after sufficient history
327
+ 4. **Compare Intent Accuracy**: Measure if fixing context access improves intent recognition accuracy
328
+
329
+ ## Implementation Priority
330
+
331
+ **High Priority**: This bug prevents the intent agent from using available conversation context, which likely:
332
+ - Reduces intent recognition accuracy for follow-up questions
333
+ - Prevents context-aware intent classification
334
+ - Wastes the hierarchical context summarization system
335
+
336
+ **Recommended Fix**: Option 2 (Use `combined_context`) as it's the simplest and most comprehensive solution.
337
+
CONTEXT_STRUCTURE_FIX_IMPLEMENTATION.md ADDED
@@ -0,0 +1,209 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Context Structure Fix Implementation
2
+
3
+ ## Summary
4
+
5
+ Fixed context structure mismatches across all agents to properly use the Context Manager's actual data structure. All agents now correctly access `interaction_contexts`, `user_context`, and `combined_context` instead of non-existent keys like `conversation_history` or `interactions`.
6
+
7
+ ## Changes Made
8
+
9
+ ### 1. Intent Recognition Agent (`src/agents/intent_agent.py`)
10
+
11
+ **Problem**: Was accessing `context.get('conversation_history', [])` which doesn't exist.
12
+
13
+ **Fix**:
14
+ - Now uses `combined_context` (preferred) or builds from `interaction_contexts` and `user_context`
15
+ - Shows last 2 interaction summaries for context awareness
16
+ - Includes user context if available
17
+ - Provides informative message when no context is available
18
+
19
+ **Key Changes**:
20
+ ```python
21
+ # OLD (line 109):
22
+ Available Context: {context.get('conversation_history', [])[-2:] if context else []}
23
+
24
+ # NEW:
25
+ # Uses combined_context if available, otherwise builds from interaction_contexts
26
+ combined_context = context.get('combined_context', '')
27
+ interaction_contexts = context.get('interaction_contexts', [])
28
+ user_context = context.get('user_context', '')
29
+ ```
30
+
31
+ **Impact**: Intent agent now sees actual conversation history, improving intent recognition accuracy for follow-up questions.
32
+
33
+ ---
34
+
35
+ ### 2. Response Synthesis Agent (`src/agents/synthesis_agent.py`)
36
+
37
+ **Problem**: Was accessing `context.get('interactions', [])` which doesn't exist.
38
+
39
+ **Fix**:
40
+ - `_build_context_section()` now uses `combined_context` (preferred) or builds from `interaction_contexts`
41
+ - Updated `_summarize_interaction_contexts()` to work with Context Manager structure
42
+ - Added backward compatibility via `_summarize_interactions()` wrapper
43
+ - Updated logging and metadata to use correct keys
44
+
45
+ **Key Changes**:
46
+ ```python
47
+ # OLD (line 534):
48
+ interactions = context.get('interactions', [])
49
+
50
+ # NEW:
51
+ combined_context = context.get('combined_context', '')
52
+ interaction_contexts = context.get('interaction_contexts', [])
53
+ user_context = context.get('user_context', '')
54
+ ```
55
+
56
+ **Impact**: Synthesis agent now uses actual conversation context for generating contextually relevant responses.
57
+
58
+ ---
59
+
60
+ ### 3. Safety Check Agent (`src/agents/safety_agent.py`)
61
+
62
+ **Problem**: Wasn't using context at all in safety analysis.
63
+
64
+ **Fix**:
65
+ - Enhanced `_build_safety_prompt()` to include context information
66
+ - Uses `user_context` and recent `interaction_contexts` for context-aware safety analysis
67
+ - Helps safety agent understand conversational context when assessing content appropriateness
68
+
69
+ **Key Changes**:
70
+ ```python
71
+ # Added context awareness:
72
+ user_context = context.get('user_context', '')
73
+ interaction_contexts = context.get('interaction_contexts', [])
74
+ # Includes context in safety analysis prompt
75
+ ```
76
+
77
+ **Impact**: Safety analysis now considers conversation context, improving appropriateness assessment.
78
+
79
+ ---
80
+
81
+ ### 4. Skills Identification Agent (`src/agents/skills_identification_agent.py`)
82
+
83
+ **Problem**: Wasn't using context in skill identification.
84
+
85
+ **Fix**:
86
+ - Enhanced `_build_market_analysis_prompt()` to accept and use context parameter
87
+ - Includes user context and recent interaction contexts in market analysis
88
+ - Helps identify skills based on conversation continuity
89
+
90
+ **Key Changes**:
91
+ ```python
92
+ # Updated method signature:
93
+ def _build_market_analysis_prompt(self, user_input: str, context: Dict[str, Any] = None)
94
+
95
+ # Added context information:
96
+ user_context = context.get('user_context', '')
97
+ interaction_contexts = context.get('interaction_contexts', [])
98
+ ```
99
+
100
+ **Impact**: Skills identification now considers conversation history for better skill relevance.
101
+
102
+ ---
103
+
104
+ ## Context Structure Reference
105
+
106
+ All agents now correctly use the Context Manager's structure:
107
+
108
+ ```python
109
+ context = {
110
+ "session_id": str,
111
+ "user_id": str,
112
+ "user_context": str, # 500-token user persona summary
113
+ "interaction_contexts": [ # List of interaction summary dicts
114
+ {
115
+ "summary": str, # 50-token interaction summary
116
+ "timestamp": str
117
+ },
118
+ ...
119
+ ],
120
+ "combined_context": str, # Pre-formatted: "[User Context]\n...\n[Interaction Context #N]\n..."
121
+ "preferences": dict,
122
+ "active_tasks": list,
123
+ "last_activity": str
124
+ }
125
+ ```
126
+
127
+ ## Implementation Strategy
128
+
129
+ ### Priority Order
130
+ 1. **Use `combined_context` first** - Pre-formatted by Context Manager, most efficient
131
+ 2. **Fallback to building from components** - If `combined_context` not available
132
+ 3. **Handle empty context gracefully** - Informative messages when no context exists
133
+
134
+ ### Context Access Pattern
135
+ ```python
136
+ # Preferred pattern used across all agents:
137
+ if context:
138
+ # Option 1: Use pre-formatted combined_context
139
+ combined_context = context.get('combined_context', '')
140
+ if combined_context:
141
+ # Use combined_context directly
142
+ context_info = combined_context
143
+
144
+ # Option 2: Build from components
145
+ else:
146
+ user_context = context.get('user_context', '')
147
+ interaction_contexts = context.get('interaction_contexts', [])
148
+ # Build context_info from components
149
+ ```
150
+
151
+ ## Testing Recommendations
152
+
153
+ ### Test Scenarios
154
+
155
+ 1. **First Turn (No Context)**
156
+ - Verify agents handle empty context gracefully
157
+ - Verify informative messages when no context available
158
+
159
+ 2. **Second Turn (1 Interaction)**
160
+ - Verify agents access `interaction_contexts[0]`
161
+ - Verify context appears in prompts
162
+
163
+ 3. **Multiple Turns (3+ Interactions)**
164
+ - Verify agents use last N interaction contexts
165
+ - Verify context accumulates correctly
166
+
167
+ 4. **With User Persona (20+ Interactions)**
168
+ - Verify `user_context` appears in prompts
169
+ - Verify `combined_context` includes user context
170
+
171
+ ### Expected Behavior
172
+
173
+ | Turn | Intent Agent Sees | Synthesis Agent Sees | Safety Agent Sees | Skills Agent Sees |
174
+ |------|------------------|---------------------|-------------------|-------------------|
175
+ | 1 | "No previous context" | Empty | No context | No context |
176
+ | 2 | Interaction #1 summary | Interaction #1 | Recent context | Recent context |
177
+ | 3+ | Last 2 interactions | All/Summarized interactions | Recent context | Recent context |
178
+ | 20+ | User context + interactions | User context + interactions | User context | User context |
179
+
180
+ ## Benefits
181
+
182
+ 1. **Intent Recognition**: Now context-aware, better accuracy for follow-up questions
183
+ 2. **Response Synthesis**: Uses conversation history for more relevant responses
184
+ 3. **Safety Analysis**: Context-aware appropriateness assessment
185
+ 4. **Skills Identification**: Considers conversation continuity for better skill matching
186
+ 5. **Consistency**: All agents use the same context structure
187
+ 6. **Performance**: Uses pre-formatted `combined_context` when available (more efficient)
188
+
189
+ ## Backward Compatibility
190
+
191
+ - Synthesis agent includes `_summarize_interactions()` wrapper for backward compatibility
192
+ - All changes are additive (enhancements) rather than breaking changes
193
+ - Fallback logic handles missing or incomplete context gracefully
194
+
195
+ ## Files Modified
196
+
197
+ 1. `src/agents/intent_agent.py` - Fixed context access in `_build_chain_of_thought_prompt()`
198
+ 2. `src/agents/synthesis_agent.py` - Fixed `_build_context_section()` and related methods
199
+ 3. `src/agents/safety_agent.py` - Enhanced `_build_safety_prompt()` with context
200
+ 4. `src/agents/skills_identification_agent.py` - Enhanced `_build_market_analysis_prompt()` with context
201
+
202
+ ## Verification
203
+
204
+ ✅ No linting errors
205
+ ✅ All agents use correct context keys
206
+ ✅ Backward compatibility maintained
207
+ ✅ Graceful handling of empty context
208
+ ✅ Consistent implementation pattern across all agents
209
+
src/agents/intent_agent.py CHANGED
@@ -101,16 +101,47 @@ class IntentRecognitionAgent:
101
  def _build_chain_of_thought_prompt(self, user_input: str, context: Dict[str, Any]) -> str:
102
  """Build Chain of Thought prompt for intent recognition"""
103
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
104
  return f"""
105
  Analyze the user's intent step by step:
106
 
107
  User Input: "{user_input}"
108
-
109
- Available Context: {context.get('conversation_history', [])[-2:] if context else []}
110
 
111
  Step 1: Identify key entities, actions, and questions in the input
112
  Step 2: Map to intent categories: {', '.join(self.intent_categories)}
113
- Step 3: Consider the conversation flow and user's likely goals
114
  Step 4: Assign confidence scores (0.0-1.0) for each relevant intent
115
  Step 5: Provide reasoning for the classification
116
 
 
101
  def _build_chain_of_thought_prompt(self, user_input: str, context: Dict[str, Any]) -> str:
102
  """Build Chain of Thought prompt for intent recognition"""
103
 
104
+ # Extract context information from Context Manager structure
105
+ context_info = ""
106
+ if context:
107
+ # Use combined_context if available (pre-formatted by Context Manager)
108
+ combined_context = context.get('combined_context', '')
109
+ if combined_context:
110
+ # Use the pre-formatted context from Context Manager
111
+ context_info = f"\n\nAvailable Context:\n{combined_context[:1000]}..." # Truncate if too long
112
+ else:
113
+ # Fallback: Build from interaction_contexts if combined_context not available
114
+ interaction_contexts = context.get('interaction_contexts', [])
115
+ user_context = context.get('user_context', '')
116
+
117
+ context_parts = []
118
+ if user_context:
119
+ context_parts.append(f"User Context: {user_context[:300]}...")
120
+
121
+ if interaction_contexts:
122
+ # Show last 2 interaction summaries for context
123
+ recent_contexts = interaction_contexts[-2:]
124
+ context_parts.append("Recent Interactions:")
125
+ for idx, ic in enumerate(recent_contexts, 1):
126
+ summary = ic.get('summary', '')
127
+ if summary:
128
+ context_parts.append(f" {idx}. {summary}")
129
+
130
+ if context_parts:
131
+ context_info = "\n\nAvailable Context:\n" + "\n".join(context_parts)
132
+
133
+ if not context_info:
134
+ context_info = "\n\nAvailable Context: No previous context available (first interaction in session)."
135
+
136
  return f"""
137
  Analyze the user's intent step by step:
138
 
139
  User Input: "{user_input}"
140
+ {context_info}
 
141
 
142
  Step 1: Identify key entities, actions, and questions in the input
143
  Step 2: Map to intent categories: {', '.join(self.intent_categories)}
144
+ Step 3: Consider the conversation flow and user's likely goals (if context available)
145
  Step 4: Assign confidence scores (0.0-1.0) for each relevant intent
146
  Step 5: Provide reasoning for the classification
147
 
src/agents/safety_agent.py CHANGED
@@ -149,12 +149,28 @@ class SafetyCheckAgent:
149
  }
150
 
151
  def _build_safety_prompt(self, response: str, context: Dict[str, Any]) -> str:
152
- """Build prompt for safety analysis"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
153
 
154
  return f"""
155
  Analyze the following text for safety concerns and provide warnings if needed:
156
 
157
  Text to analyze: "{response[:500]}..." # Truncate for large responses
 
158
 
159
  Analyze for:
160
  1. Toxicity or harmful language
@@ -162,6 +178,8 @@ class SafetyCheckAgent:
162
  3. Privacy or security concerns
163
  4. Controversial or sensitive topics
164
 
 
 
165
  Provide analysis in JSON format with:
166
  - safety_scores for each category (0-1 scale)
167
  - detected_issues list
 
149
  }
150
 
151
  def _build_safety_prompt(self, response: str, context: Dict[str, Any]) -> str:
152
+ """Build prompt for safety analysis with context awareness"""
153
+
154
+ # Extract relevant context information for safety analysis
155
+ context_info = ""
156
+ if context:
157
+ # Get user context if available (might indicate user's background/preferences)
158
+ user_context = context.get('user_context', '')
159
+ if user_context:
160
+ context_info = f"\n\nUser Context (for safety context): {user_context[:200]}..."
161
+
162
+ # Optionally include recent interaction context to understand conversation flow
163
+ interaction_contexts = context.get('interaction_contexts', [])
164
+ if interaction_contexts:
165
+ recent_context = interaction_contexts[-1].get('summary', '') if interaction_contexts else ''
166
+ if recent_context:
167
+ context_info += f"\nRecent conversation: {recent_context[:200]}..."
168
 
169
  return f"""
170
  Analyze the following text for safety concerns and provide warnings if needed:
171
 
172
  Text to analyze: "{response[:500]}..." # Truncate for large responses
173
+ {context_info}
174
 
175
  Analyze for:
176
  1. Toxicity or harmful language
 
178
  3. Privacy or security concerns
179
  4. Controversial or sensitive topics
180
 
181
+ Consider the conversation context when assessing whether content is appropriate in this specific conversational context.
182
+
183
  Provide analysis in JSON format with:
184
  - safety_scores for each category (0-1 scale)
185
  - detected_issues list
src/agents/skills_identification_agent.py CHANGED
@@ -158,8 +158,8 @@ class SkillsIdentificationAgent:
158
 
159
  if self.llm_router:
160
  try:
161
- # Build market analysis prompt
162
- market_prompt = self._build_market_analysis_prompt(user_input)
163
 
164
  logger.info(f"{self.agent_id} calling reasoning_primary for market analysis")
165
  llm_response = await self.llm_router.route_inference(
@@ -211,8 +211,8 @@ class SkillsIdentificationAgent:
211
  # Fallback to rule-based classification
212
  return self._rule_based_skill_classification(user_input)
213
 
214
- def _build_market_analysis_prompt(self, user_input: str) -> str:
215
- """Build prompt for market analysis using reasoning_primary model"""
216
 
217
  market_data = "\n".join([
218
  f"- {category}: {data['market_share']}% market share, {data['growth_rate']}% growth rate"
@@ -224,9 +224,29 @@ class SkillsIdentificationAgent:
224
  for category, data in self.market_categories.items()
225
  ])
226
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  return f"""Analyze the following user input and identify the most relevant industry categories and specialized skills based on current market data.
228
 
229
  User Input: "{user_input}"
 
230
 
231
  Current Market Distribution:
232
  {market_data}
@@ -235,10 +255,11 @@ Specialized Skills by Category (top 3 per category):
235
  {specialized_skills}
236
 
237
  Task:
238
- 1. Identify which industry categories are most relevant to the user's input
239
  2. Select 1-3 specialized skills from each relevant category that best match the user's needs
240
  3. Provide market share percentages and growth rates for identified categories
241
  4. Explain your reasoning for each selection
 
242
 
243
  Respond in JSON format:
244
  {{
 
158
 
159
  if self.llm_router:
160
  try:
161
+ # Build market analysis prompt with context
162
+ market_prompt = self._build_market_analysis_prompt(user_input, context)
163
 
164
  logger.info(f"{self.agent_id} calling reasoning_primary for market analysis")
165
  llm_response = await self.llm_router.route_inference(
 
211
  # Fallback to rule-based classification
212
  return self._rule_based_skill_classification(user_input)
213
 
214
+ def _build_market_analysis_prompt(self, user_input: str, context: Dict[str, Any] = None) -> str:
215
+ """Build prompt for market analysis using reasoning_primary model with optional context"""
216
 
217
  market_data = "\n".join([
218
  f"- {category}: {data['market_share']}% market share, {data['growth_rate']}% growth rate"
 
224
  for category, data in self.market_categories.items()
225
  ])
226
 
227
+ # Add context information if available
228
+ context_info = ""
229
+ if context:
230
+ user_context = context.get('user_context', '')
231
+ interaction_contexts = context.get('interaction_contexts', [])
232
+
233
+ if user_context:
234
+ context_info = f"\n\nUser Context (persona summary): {user_context[:300]}..."
235
+
236
+ if interaction_contexts:
237
+ # Include recent interaction context to understand topic continuity
238
+ recent_contexts = interaction_contexts[-2:] # Last 2 interactions
239
+ if recent_contexts:
240
+ context_info += "\n\nRecent conversation context:"
241
+ for idx, ic in enumerate(recent_contexts, 1):
242
+ summary = ic.get('summary', '')
243
+ if summary:
244
+ context_info += f"\n {idx}. {summary}"
245
+
246
  return f"""Analyze the following user input and identify the most relevant industry categories and specialized skills based on current market data.
247
 
248
  User Input: "{user_input}"
249
+ {context_info}
250
 
251
  Current Market Distribution:
252
  {market_data}
 
255
  {specialized_skills}
256
 
257
  Task:
258
+ 1. Identify which industry categories are most relevant to the user's input (consider conversation context if provided)
259
  2. Select 1-3 specialized skills from each relevant category that best match the user's needs
260
  3. Provide market share percentages and growth rates for identified categories
261
  4. Explain your reasoning for each selection
262
+ 5. If conversation context is available, consider how previous topics might inform the skill identification
263
 
264
  Respond in JSON format:
265
  {{
src/agents/synthesis_agent.py CHANGED
@@ -296,7 +296,8 @@ class EnhancedSynthesisAgent:
296
 
297
  logger.info(f"{self.agent_id} synthesizing {len(agent_outputs)} agent outputs")
298
  if context:
299
- logger.info(f"{self.agent_id} context has {len(context.get('interactions', []))} interactions")
 
300
 
301
  # STEP 1: Extract skill probabilities from skills_result
302
  skill_probabilities = self._extract_skill_probabilities(skills_result)
@@ -354,7 +355,8 @@ class EnhancedSynthesisAgent:
354
  "synthesis_quality_metrics": self._calculate_quality_metrics({"final_response": clean_response}),
355
  "synthesis_metadata": {
356
  "agent_outputs_count": len(agent_outputs),
357
- "context_interactions": len(context.get('interactions', [])) if context else 0,
 
358
  "expert_enhanced": True,
359
  "processing_timestamp": datetime.now().isoformat()
360
  }
@@ -527,70 +529,112 @@ Response:"""
527
  return prompt
528
 
529
  def _build_context_section(self, context: Dict[str, Any]) -> str:
530
- """Build context section with summarization for long conversations"""
 
 
 
 
 
 
531
  if not context:
532
  return ""
533
 
534
- interactions = context.get('interactions', [])
535
-
536
- if len(interactions) <= 8:
537
- # Show all interactions for short conversations
538
- context_section = "\n\nPrevious conversation:\n"
539
- for i, interaction in enumerate(interactions, 1):
540
- context_section += f"Q{i}: {interaction.get('user_input', '')}\n"
541
- if interaction.get('assistant_response') or interaction.get('response'):
542
- context_section += f"A{i}: {interaction.get('assistant_response') or interaction.get('response', '')}\n\n"
543
- else:
544
- # Summarize older interactions, show recent ones in full
545
- recent_interactions = interactions[-8:] # Last 8 interactions
546
- older_interactions = interactions[:-8] # Everything before last 8
547
-
548
- # Create summary of older interactions
549
- summary = self._summarize_interactions(older_interactions)
550
-
551
- context_section = f"\n\nConversation Summary (earlier context):\n{summary}\n\nRecent conversation details:\n"
552
-
553
- for i, interaction in enumerate(recent_interactions, 1):
554
- context_section += f"Q{i}: {interaction.get('user_input', '')}\n"
555
- if interaction.get('assistant_response') or interaction.get('response'):
556
- context_section += f"A{i}: {interaction.get('assistant_response') or interaction.get('response', '')}\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
557
 
558
  return context_section
559
 
560
- def _summarize_interactions(self, interactions: List[Dict[str, Any]]) -> str:
561
- """Summarize older interactions to preserve key context"""
562
- if not interactions:
 
 
 
 
 
563
  return "No prior context."
564
 
565
- # Extract key topics and themes
566
  topics = []
567
  key_points = []
568
 
569
- for interaction in interactions:
570
- user_input = interaction.get('user_input', '')
571
- assistant_response = interaction.get('assistant_response') or interaction.get('response', '')
572
 
573
- # Extract topics (simple keyword extraction)
574
- if user_input:
575
- # Simple topic extraction - could be enhanced with NLP
576
- user_words = user_input.lower().split()
577
- key_terms = [word for word in user_words if len(word) > 4][:3]
578
  topics.extend(key_terms)
579
-
580
- # Extract key points from responses (first sentence)
581
- if assistant_response:
582
- first_sentence = assistant_response.split('.')[0][:100]
583
- if first_sentence:
584
- key_points.append(first_sentence + "...")
585
 
586
  # Build summary
587
  unique_topics = list(set(topics))[:5] # Top 5 unique topics
588
- recent_points = key_points[-3:] # Last 3 key points
589
 
590
- summary = f"Topics discussed: {', '.join(unique_topics)}\n"
591
- summary += f"Key points: {' '.join(recent_points)}"
592
 
593
- return summary
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
594
 
595
  def _extract_intent_info(self, agent_outputs: List[Dict[str, Any]]) -> Dict[str, Any]:
596
  """Extract intent information from agent outputs"""
 
296
 
297
  logger.info(f"{self.agent_id} synthesizing {len(agent_outputs)} agent outputs")
298
  if context:
299
+ interaction_count = len(context.get('interaction_contexts', [])) if context else 0
300
+ logger.info(f"{self.agent_id} context has {interaction_count} interaction contexts")
301
 
302
  # STEP 1: Extract skill probabilities from skills_result
303
  skill_probabilities = self._extract_skill_probabilities(skills_result)
 
355
  "synthesis_quality_metrics": self._calculate_quality_metrics({"final_response": clean_response}),
356
  "synthesis_metadata": {
357
  "agent_outputs_count": len(agent_outputs),
358
+ "context_interactions": len(context.get('interaction_contexts', [])) if context else 0,
359
+ "user_context_available": bool(context.get('user_context', '')) if context else False,
360
  "expert_enhanced": True,
361
  "processing_timestamp": datetime.now().isoformat()
362
  }
 
529
  return prompt
530
 
531
  def _build_context_section(self, context: Dict[str, Any]) -> str:
532
+ """Build context section with summarization for long conversations
533
+
534
+ Uses Context Manager structure:
535
+ - combined_context: Pre-formatted context string (preferred)
536
+ - interaction_contexts: List of interaction summaries with 'summary' and 'timestamp'
537
+ - user_context: User persona summary string
538
+ """
539
  if not context:
540
  return ""
541
 
542
+ # Prefer combined_context if available (pre-formatted by Context Manager)
543
+ combined_context = context.get('combined_context', '')
544
+ if combined_context:
545
+ # Use the pre-formatted context from Context Manager
546
+ # It already includes User Context and Interaction Contexts formatted
547
+ return f"\n\nConversation Context:\n{combined_context}"
548
+
549
+ # Fallback: Build from individual components if combined_context not available
550
+ interaction_contexts = context.get('interaction_contexts', [])
551
+ user_context = context.get('user_context', '')
552
+
553
+ context_section = ""
554
+
555
+ # Add user context if available
556
+ if user_context:
557
+ context_section += f"\n\nUser Context (Persona Summary):\n{user_context[:500]}...\n"
558
+
559
+ # Add interaction contexts
560
+ if interaction_contexts:
561
+ if len(interaction_contexts) <= 8:
562
+ # Show all interaction summaries for short conversations
563
+ context_section += "\n\nPrevious Conversation Summary:\n"
564
+ for i, ic in enumerate(interaction_contexts, 1):
565
+ summary = ic.get('summary', '')
566
+ if summary:
567
+ context_section += f" {i}. {summary}\n"
568
+ else:
569
+ # Summarize older interactions, show recent ones
570
+ recent_contexts = interaction_contexts[-8:] # Last 8 interactions
571
+ older_contexts = interaction_contexts[:-8] # Everything before last 8
572
+
573
+ # Create summary of older interactions
574
+ summary = self._summarize_interaction_contexts(older_contexts)
575
+
576
+ context_section += f"\n\nConversation Summary (earlier context):\n{summary}\n\nRecent Conversation:\n"
577
+
578
+ for i, ic in enumerate(recent_contexts, 1):
579
+ summary_text = ic.get('summary', '')
580
+ if summary_text:
581
+ context_section += f" {i}. {summary_text}\n"
582
 
583
  return context_section
584
 
585
+ def _summarize_interaction_contexts(self, interaction_contexts: List[Dict[str, Any]]) -> str:
586
+ """Summarize older interaction contexts to preserve key context
587
+
588
+ Uses Context Manager structure where interaction_contexts contains:
589
+ - summary: 50-token interaction summary string
590
+ - timestamp: Interaction timestamp
591
+ """
592
+ if not interaction_contexts:
593
  return "No prior context."
594
 
595
+ # Extract key topics and themes from summaries
596
  topics = []
597
  key_points = []
598
 
599
+ for ic in interaction_contexts:
600
+ summary = ic.get('summary', '')
 
601
 
602
+ if summary:
603
+ # Extract topics from summary (simple keyword extraction)
604
+ # Summaries are already condensed, so extract meaningful terms
605
+ words = summary.lower().split()
606
+ key_terms = [word for word in words if len(word) > 4][:3]
607
  topics.extend(key_terms)
608
+
609
+ # Use summary as key point (already a summary)
610
+ key_points.append(summary[:150])
 
 
 
611
 
612
  # Build summary
613
  unique_topics = list(set(topics))[:5] # Top 5 unique topics
614
+ recent_points = key_points[-5:] # Last 5 key points
615
 
616
+ summary_text = f"Topics discussed: {', '.join(unique_topics) if unique_topics else 'General discussion'}\n"
617
+ summary_text += f"Key points: {' | '.join(recent_points) if recent_points else 'No specific points'}"
618
 
619
+ return summary_text
620
+
621
+ def _summarize_interactions(self, interactions: List[Dict[str, Any]]) -> str:
622
+ """Legacy method for backward compatibility - delegates to _summarize_interaction_contexts"""
623
+ # Convert old format to new format if needed
624
+ if interactions and 'summary' in interactions[0]:
625
+ # Already in new format
626
+ return self._summarize_interaction_contexts(interactions)
627
+ else:
628
+ # Old format - convert
629
+ interaction_contexts = []
630
+ for interaction in interactions:
631
+ user_input = interaction.get('user_input', '')
632
+ assistant_response = interaction.get('assistant_response') or interaction.get('response', '')
633
+ # Create a simple summary
634
+ summary = f"User asked: {user_input[:100]}..." if user_input else ""
635
+ if summary:
636
+ interaction_contexts.append({'summary': summary})
637
+ return self._summarize_interaction_contexts(interaction_contexts)
638
 
639
  def _extract_intent_info(self, agent_outputs: List[Dict[str, Any]]) -> Dict[str, Any]:
640
  """Extract intent information from agent outputs"""