azettl commited on
Commit
a1abb42
·
verified ·
1 Parent(s): 86dda1b

add OpenFloorResearchAgent class

Browse files
Files changed (1) hide show
  1. app.py +169 -0
app.py CHANGED
@@ -16,6 +16,9 @@ from gradio_consilium_roundtable import consilium_roundtable
16
  from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, InferenceClientModel, VisitWebpageTool, Tool
17
  from research_tools import EnhancedResearchAgent
18
  from enhanced_search_functions import ENHANCED_SEARCH_FUNCTIONS
 
 
 
19
 
20
  # Load environment variables
21
  load_dotenv()
@@ -36,6 +39,172 @@ avatar_images = {
36
  "Meta-Llama-3.3-70B-Instruct": "https://registry.npmmirror.com/@lobehub/icons-static-png/1.46.0/files/dark/meta-color.png",
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  def get_session_id(request: gr.Request = None) -> str:
40
  """Generate or retrieve session ID"""
41
  if request and hasattr(request, 'session_hash'):
 
16
  from smolagents import CodeAgent, DuckDuckGoSearchTool, FinalAnswerTool, InferenceClientModel, VisitWebpageTool, Tool
17
  from research_tools import EnhancedResearchAgent
18
  from enhanced_search_functions import ENHANCED_SEARCH_FUNCTIONS
19
+ from openfloor import *
20
+ from openfloor.manifest import *
21
+ from openfloor.envelope import *
22
 
23
  # Load environment variables
24
  load_dotenv()
 
39
  "Meta-Llama-3.3-70B-Instruct": "https://registry.npmmirror.com/@lobehub/icons-static-png/1.46.0/files/dark/meta-color.png",
40
  }
41
 
42
+ class OpenFloorResearchAgent:
43
+ """Wrap research tools as independent OpenFloor agents"""
44
+
45
+ def __init__(self, tool: BaseTool, port: int = None):
46
+ self.tool = tool
47
+ self.port = port
48
+ self.manifest = self._create_manifest()
49
+ self.active_conversations = {}
50
+
51
+ def _create_manifest(self) -> Manifest:
52
+ """Create OpenFloor manifest for this research agent"""
53
+ speaker_uri = f"tag:research.consilium,2025:{self.tool.name.lower().replace(' ', '-')}-agent"
54
+
55
+ # Tool-specific keyphrases and capabilities
56
+ tool_configs = {
57
+ 'Web Search': {
58
+ 'keyphrases': ['web', 'search', 'current', 'news', 'latest', 'recent'],
59
+ 'synopsis': 'Real-time web search for current information and trends'
60
+ },
61
+ 'Wikipedia': {
62
+ 'keyphrases': ['facts', 'encyclopedia', 'history', 'knowledge', 'definition'],
63
+ 'synopsis': 'Authoritative encyclopedia research and factual verification'
64
+ },
65
+ 'arXiv': {
66
+ 'keyphrases': ['academic', 'research', 'papers', 'science', 'study'],
67
+ 'synopsis': 'Academic research papers and scientific literature analysis'
68
+ },
69
+ 'GitHub': {
70
+ 'keyphrases': ['technology', 'code', 'development', 'programming', 'trends'],
71
+ 'synopsis': 'Technology adoption trends and software development analysis'
72
+ },
73
+ 'SEC EDGAR': {
74
+ 'keyphrases': ['financial', 'company', 'earnings', 'sec', 'filings'],
75
+ 'synopsis': 'Corporate financial data and SEC regulatory filings research'
76
+ }
77
+ }
78
+
79
+ config = tool_configs.get(self.tool.name, {
80
+ 'keyphrases': ['research', 'data'],
81
+ 'synopsis': self.tool.description
82
+ })
83
+
84
+ return Manifest(
85
+ identification=Identification(
86
+ speakerUri=speaker_uri,
87
+ serviceUrl=f"http://localhost:{self.port}/openfloor" if self.port else None,
88
+ conversationalName=f"{self.tool.name} Research Agent",
89
+ organization="Consilium Research Division",
90
+ role="Research Specialist",
91
+ synopsis=config['synopsis']
92
+ ),
93
+ capabilities=[
94
+ Capability(
95
+ keyphrases=config['keyphrases'],
96
+ descriptions=[self.tool.description],
97
+ languages=["en-us"]
98
+ )
99
+ ]
100
+ )
101
+
102
+ def handle_utterance_event(self, envelope: Envelope) -> Envelope:
103
+ """Handle research requests from AI experts"""
104
+ # Extract the query from the utterance
105
+ for event in envelope.events:
106
+ if hasattr(event, 'eventType') and event.eventType == 'utterance':
107
+ dialog_event = event.parameters.get('dialogEvent')
108
+ if dialog_event and hasattr(dialog_event, 'features'):
109
+ text_feature = dialog_event.features.get('text')
110
+ if text_feature and hasattr(text_feature, 'tokens'):
111
+ query_text = ' '.join([token.get('value', '') for token in text_feature.tokens])
112
+
113
+ # Perform the research
114
+ research_result = self.tool.search(query_text)
115
+
116
+ # Create response envelope
117
+ return self._create_response_envelope(envelope, research_result, query_text)
118
+
119
+ return self._create_error_response(envelope, "Could not extract query from request")
120
+
121
+ def _create_response_envelope(self, original_envelope: Envelope, research_result: str, query: str) -> Envelope:
122
+ """Create OpenFloor response envelope with research results"""
123
+
124
+ # Create response dialog event
125
+ response_dialog = DialogEvent(
126
+ speakerUri=self.manifest.identification.speakerUri,
127
+ features={
128
+ "text": TextFeature(values=[research_result])
129
+ }
130
+ )
131
+
132
+ # Create context with research metadata
133
+ research_context = ContextEvent(
134
+ parameters={
135
+ "research_tool": self.tool.name,
136
+ "query": query,
137
+ "source": self.tool.name.lower().replace(' ', '_'),
138
+ "confidence": self._assess_result_confidence(research_result),
139
+ "timestamp": datetime.now().isoformat()
140
+ }
141
+ )
142
+
143
+ # Create response envelope
144
+ response_envelope = Envelope(
145
+ conversation=original_envelope.conversation,
146
+ sender=Sender(speakerUri=self.manifest.identification.speakerUri),
147
+ events=[
148
+ UtteranceEvent(dialogEvent=response_dialog),
149
+ research_context
150
+ ]
151
+ )
152
+
153
+ return response_envelope
154
+
155
+ def _assess_result_confidence(self, result: str) -> float:
156
+ """Assess confidence in research result quality"""
157
+ if not result or len(result) < 50:
158
+ return 0.3
159
+
160
+ quality_indicators = [
161
+ (len(result) > 500, 0.2), # Substantial content
162
+ (any(year in result for year in ['2024', '2025']), 0.2), # Recent data
163
+ (result.count('\n') > 5, 0.1), # Well-structured
164
+ ('error' not in result.lower(), 0.3), # No errors
165
+ (any(indicator in result.lower() for indicator in ['data', 'study', 'research']), 0.2) # Authoritative
166
+ ]
167
+
168
+ confidence = 0.5 # Base confidence
169
+ for condition, boost in quality_indicators:
170
+ if condition:
171
+ confidence += boost
172
+
173
+ return min(1.0, confidence)
174
+
175
+ def _create_error_response(self, original_envelope: Envelope, error_msg: str) -> Envelope:
176
+ """Create error response envelope"""
177
+ error_dialog = DialogEvent(
178
+ speakerUri=self.manifest.identification.speakerUri,
179
+ features={
180
+ "text": TextFeature(values=[f"Research error: {error_msg}"])
181
+ }
182
+ )
183
+
184
+ return Envelope(
185
+ conversation=original_envelope.conversation,
186
+ sender=Sender(speakerUri=self.manifest.identification.speakerUri),
187
+ events=[UtteranceEvent(dialogEvent=error_dialog)]
188
+ )
189
+
190
+ def join_conversation(self, conversation_id: str) -> bool:
191
+ """Join a conversation as an active research agent"""
192
+ self.active_conversations[conversation_id] = {
193
+ 'joined_at': datetime.now(),
194
+ 'status': 'active'
195
+ }
196
+ return True
197
+
198
+ def leave_conversation(self, conversation_id: str) -> bool:
199
+ """Leave a conversation"""
200
+ if conversation_id in self.active_conversations:
201
+ del self.active_conversations[conversation_id]
202
+ return True
203
+
204
+ def get_manifest(self) -> Manifest:
205
+ """Return the OpenFloor manifest for this research agent"""
206
+ return self.manifest
207
+
208
  def get_session_id(request: gr.Request = None) -> str:
209
  """Generate or retrieve session ID"""
210
  if request and hasattr(request, 'session_hash'):