azettl commited on
Commit
cbf9ac1
Β·
verified Β·
1 Parent(s): 3bee4f9

Update openfloor/OpenFloorResearchAgent.py

Browse files
Files changed (1) hide show
  1. openfloor/OpenFloorResearchAgent.py +185 -0
openfloor/OpenFloorResearchAgent.py CHANGED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class OpenFloorResearchAgent:
2
+ """Wrap research tools as independent OpenFloor agents"""
3
+
4
+ def __init__(self, tool: BaseTool, port: int = None):
5
+ self.tool = tool
6
+ self.port = port
7
+ self.manifest = self._create_manifest()
8
+ self.active_conversations = {}
9
+
10
+ def _create_manifest(self) -> Manifest:
11
+ """Create OpenFloor manifest for this research agent"""
12
+ speaker_uri = f"tag:research.consilium,2025:{self.tool.name.lower().replace(' ', '-')}-agent"
13
+
14
+ # Tool-specific keyphrases and capabilities
15
+ tool_configs = {
16
+ 'Web Search': {
17
+ 'keyphrases': ['web', 'search', 'current', 'news', 'latest', 'recent'],
18
+ 'synopsis': 'Real-time web search for current information and trends'
19
+ },
20
+ 'Wikipedia': {
21
+ 'keyphrases': ['facts', 'encyclopedia', 'history', 'knowledge', 'definition'],
22
+ 'synopsis': 'Authoritative encyclopedia research and factual verification'
23
+ },
24
+ 'arXiv': {
25
+ 'keyphrases': ['academic', 'research', 'papers', 'science', 'study'],
26
+ 'synopsis': 'Academic research papers and scientific literature analysis'
27
+ },
28
+ 'GitHub': {
29
+ 'keyphrases': ['technology', 'code', 'development', 'programming', 'trends'],
30
+ 'synopsis': 'Technology adoption trends and software development analysis'
31
+ },
32
+ 'SEC EDGAR': {
33
+ 'keyphrases': ['financial', 'company', 'earnings', 'sec', 'filings'],
34
+ 'synopsis': 'Corporate financial data and SEC regulatory filings research'
35
+ }
36
+ }
37
+
38
+ config = tool_configs.get(self.tool.name, {
39
+ 'keyphrases': ['research', 'data'],
40
+ 'synopsis': self.tool.description
41
+ })
42
+
43
+ return Manifest(
44
+ identification=Identification(
45
+ speakerUri=speaker_uri,
46
+ serviceUrl=f"http://localhost:{self.port}/openfloor" if self.port else None,
47
+ conversationalName=f"{self.tool.name} Research Agent",
48
+ organization="Consilium Research Division",
49
+ role="Research Specialist",
50
+ synopsis=config['synopsis']
51
+ ),
52
+ capabilities=[
53
+ Capability(
54
+ keyphrases=config['keyphrases'],
55
+ descriptions=[self.tool.description],
56
+ languages=["en-us"]
57
+ )
58
+ ]
59
+ )
60
+
61
+ def handle_utterance_event(self, envelope: Envelope) -> Envelope:
62
+ """Handle research requests from AI experts"""
63
+ print(f"πŸ” DEBUG: {self.tool.name} - Starting handle_utterance_event")
64
+
65
+ # Extract the query from the utterance
66
+ for event in envelope.events:
67
+ if hasattr(event, 'eventType') and event.eventType == 'utterance':
68
+ dialog_event = event.parameters.get('dialogEvent')
69
+
70
+ if dialog_event and isinstance(dialog_event, dict):
71
+ # dialog_event is a dict, not an object - use dict access
72
+ features = dialog_event.get('features')
73
+ print(f"πŸ” DEBUG: features: {features}")
74
+
75
+ if features and 'text' in features:
76
+ text_feature = features['text']
77
+ print(f"πŸ” DEBUG: text_feature: {text_feature}")
78
+
79
+ if 'tokens' in text_feature:
80
+ tokens = text_feature['tokens']
81
+ query_text = ' '.join([token.get('value', '') for token in tokens])
82
+
83
+ print(f"πŸ” DEBUG: {self.tool.name} received query: '{query_text}'")
84
+
85
+ # Perform the research
86
+ import time
87
+ start_time = time.time()
88
+ research_result = self.tool.search(query_text)
89
+ end_time = time.time()
90
+
91
+ print(f"πŸ” DEBUG: {self.tool.name} completed in {end_time - start_time:.2f}s")
92
+ print(f"πŸ” DEBUG: Result length: {len(research_result)} chars")
93
+ print(f"πŸ” DEBUG: Result preview: {research_result[:200]}...")
94
+
95
+ # Create response envelope
96
+ return self._create_response_envelope(envelope, research_result, query_text)
97
+
98
+ return self._create_error_response(envelope, "Could not extract query from request")
99
+
100
+ def _create_response_envelope(self, original_envelope: Envelope, research_result: str, query: str) -> Envelope:
101
+ """Create OpenFloor response envelope with research results"""
102
+
103
+ # Create response dialog event
104
+ response_dialog = DialogEvent(
105
+ speakerUri=self.manifest.identification.speakerUri,
106
+ features={
107
+ "text": TextFeature(values=[research_result])
108
+ }
109
+ )
110
+
111
+ # Create context with research metadata
112
+ research_context = ContextEvent(
113
+ parameters={
114
+ "research_tool": self.tool.name,
115
+ "query": query,
116
+ "source": self.tool.name.lower().replace(' ', '_'),
117
+ "confidence": self._assess_result_confidence(research_result),
118
+ "timestamp": datetime.now().isoformat()
119
+ }
120
+ )
121
+
122
+ # Create response envelope
123
+ response_envelope = Envelope(
124
+ conversation=original_envelope.conversation,
125
+ sender=Sender(speakerUri=self.manifest.identification.speakerUri),
126
+ events=[
127
+ UtteranceEvent(dialogEvent=response_dialog),
128
+ research_context
129
+ ]
130
+ )
131
+
132
+ return response_envelope
133
+
134
+ def _assess_result_confidence(self, result: str) -> float:
135
+ """Assess confidence in research result quality"""
136
+ if not result or len(result) < 50:
137
+ return 0.3
138
+
139
+ quality_indicators = [
140
+ (len(result) > 500, 0.2), # Substantial content
141
+ (any(year in result for year in ['2024', '2025']), 0.2), # Recent data
142
+ (result.count('\n') > 5, 0.1), # Well-structured
143
+ ('error' not in result.lower(), 0.3), # No errors
144
+ (any(indicator in result.lower() for indicator in ['data', 'study', 'research']), 0.2) # Authoritative
145
+ ]
146
+
147
+ confidence = 0.5 # Base confidence
148
+ for condition, boost in quality_indicators:
149
+ if condition:
150
+ confidence += boost
151
+
152
+ return min(1.0, confidence)
153
+
154
+ def _create_error_response(self, original_envelope: Envelope, error_msg: str) -> Envelope:
155
+ """Create error response envelope"""
156
+ error_dialog = DialogEvent(
157
+ speakerUri=self.manifest.identification.speakerUri,
158
+ features={
159
+ "text": TextFeature(values=[f"Research error: {error_msg}"])
160
+ }
161
+ )
162
+
163
+ return Envelope(
164
+ conversation=original_envelope.conversation,
165
+ sender=Sender(speakerUri=self.manifest.identification.speakerUri),
166
+ events=[UtteranceEvent(dialogEvent=error_dialog)]
167
+ )
168
+
169
+ def join_conversation(self, conversation_id: str) -> bool:
170
+ """Join a conversation as an active research agent"""
171
+ self.active_conversations[conversation_id] = {
172
+ 'joined_at': datetime.now(),
173
+ 'status': 'active'
174
+ }
175
+ return True
176
+
177
+ def leave_conversation(self, conversation_id: str) -> bool:
178
+ """Leave a conversation"""
179
+ if conversation_id in self.active_conversations:
180
+ del self.active_conversations[conversation_id]
181
+ return True
182
+
183
+ def get_manifest(self) -> Manifest:
184
+ """Return the OpenFloor manifest for this research agent"""
185
+ return self.manifest