rdune71 commited on
Commit
03df531
·
1 Parent(s): dcaf42a
Files changed (2) hide show
  1. app.py +23 -11
  2. modules/analyzer.py +72 -1
app.py CHANGED
@@ -43,23 +43,27 @@ class ResearchOrchestrator:
43
 
44
  logging.info(f"Retrieved {len(search_results)} results")
45
 
46
- # Step 3: Analyze content
47
- progress(0.5, desc="🧠 Analyzing search results...")
48
- yield "🧠 Analyzing search results...\n\n⏳ The AI model may be initializing. This could take a few minutes if it's the first request..."
49
- analysis = self.analyzer.analyze(query, search_results)
 
 
 
 
 
50
 
51
  # Check if analysis was successful
52
- if analysis.startswith("⚠️") or analysis.startswith("Analysis failed"):
53
- logging.warning(f"Analysis failed: {analysis}")
54
  progress(0.8, desc="⚠️ Analysis failed")
55
- yield analysis
56
  return
57
 
58
- logging.info("Analysis completed successfully")
59
 
60
  # Step 4: Manage citations
61
  progress(0.8, desc="📎 Adding citations...")
62
- cited_analysis = self.citation_manager.add_citations(analysis, search_results)
63
  logging.info("Citations added")
64
 
65
  # Step 5: Format output
@@ -119,7 +123,7 @@ def initialize_modules():
119
  # Initialize orchestrator
120
  orchestrator = initialize_modules()
121
 
122
- # Custom CSS for spinner
123
  custom_css = """
124
  .spinner {
125
  border: 4px solid #f3f3f3;
@@ -131,6 +135,14 @@ custom_css = """
131
  display: inline-block;
132
  margin-right: 8px;
133
  }
 
 
 
 
 
 
 
 
134
  @keyframes spin {
135
  0% { transform: rotate(0deg); }
136
  100% { transform: rotate(360deg); }
@@ -158,7 +170,7 @@ with gr.Blocks(css=custom_css, title="Research Assistant") as demo:
158
  submit_btn = gr.Button("Research", variant="primary")
159
 
160
  with gr.Column():
161
- output = gr.Markdown(label="Analysis Results")
162
 
163
  # Status indicator with spinner
164
  status_indicator = gr.HTML("<div id='status'><span class='spinner'></span> Ready for your research query</div>")
 
43
 
44
  logging.info(f"Retrieved {len(search_results)} results")
45
 
46
+ # Step 3: Analyze content with streaming
47
+ progress(0.5, desc="🧠 Analyzing search results (streaming)...")
48
+ yield "## 🧠 AI Analysis (Live Streaming)\n\n"
49
+
50
+ # Collect all streamed content
51
+ full_analysis = ""
52
+ for chunk in self.analyzer.analyze_stream(query, search_results):
53
+ full_analysis += chunk
54
+ yield chunk
55
 
56
  # Check if analysis was successful
57
+ if full_analysis.startswith("⚠️") or full_analysis.startswith("Analysis failed"):
58
+ logging.warning(f"Analysis failed: {full_analysis}")
59
  progress(0.8, desc="⚠️ Analysis failed")
 
60
  return
61
 
62
+ logging.info("Analysis streaming completed successfully")
63
 
64
  # Step 4: Manage citations
65
  progress(0.8, desc="📎 Adding citations...")
66
+ cited_analysis = self.citation_manager.add_citations(full_analysis, search_results)
67
  logging.info("Citations added")
68
 
69
  # Step 5: Format output
 
123
  # Initialize orchestrator
124
  orchestrator = initialize_modules()
125
 
126
+ # Custom CSS for spinner and streaming
127
  custom_css = """
128
  .spinner {
129
  border: 4px solid #f3f3f3;
 
135
  display: inline-block;
136
  margin-right: 8px;
137
  }
138
+ .streaming-content {
139
+ white-space: pre-wrap;
140
+ font-family: monospace;
141
+ background-color: #f8f9fa;
142
+ padding: 10px;
143
+ border-radius: 5px;
144
+ margin: 10px 0;
145
+ }
146
  @keyframes spin {
147
  0% { transform: rotate(0deg); }
148
  100% { transform: rotate(360deg); }
 
170
  submit_btn = gr.Button("Research", variant="primary")
171
 
172
  with gr.Column():
173
+ output = gr.Markdown(label="Analysis Results", elem_classes=["streaming-content"])
174
 
175
  # Status indicator with spinner
176
  status_indicator = gr.HTML("<div id='status'><span class='spinner'></span> Ready for your research query</div>")
modules/analyzer.py CHANGED
@@ -80,9 +80,80 @@ class Analyzer:
80
  logging.warning("⏰ Server initialization timeout reached")
81
  return False
82
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  def analyze(self, query, search_results):
84
  """
85
- Analyze search results using the custom LLM
86
  """
87
  # Prepare context from search results
88
  context = "\n\n".join([
 
80
  logging.warning("⏰ Server initialization timeout reached")
81
  return False
82
 
83
+ def analyze_stream(self, query, search_results):
84
+ """
85
+ Analyze search results using the custom LLM with streaming output
86
+ Yields chunks of the response as they arrive
87
+ """
88
+ # Prepare context from search results
89
+ context = "\n\n".join([
90
+ f"Source: {result.get('url', 'N/A')}\nTitle: {result.get('title', 'N/A')}\nContent: {result.get('content', 'N/A')}"
91
+ for result in search_results[:5] # Limit to top 5 for context
92
+ ])
93
+
94
+ prompt = f"""
95
+ You are an expert research analyst. Analyze the following query and information to provide a comprehensive summary.
96
+
97
+ Query: {query}
98
+
99
+ Information:
100
+ {context}
101
+
102
+ Please provide:
103
+ 1. A brief overview of the topic
104
+ 2. Key findings or developments
105
+ 3. Different perspectives or approaches
106
+ 4. Potential implications or future directions
107
+ 5. Any controversies or conflicting viewpoints
108
+
109
+ Structure your response clearly with these sections. If there is insufficient information, state that clearly.
110
+ """
111
+
112
+ try:
113
+ # First check if server is ready
114
+ logging.info("Checking if server is ready for analysis...")
115
+ if not self.wait_for_server(timeout=180): # 3 minutes timeout
116
+ error_msg = "⚠️ The AI model server is still initializing. Please try again in a few minutes."
117
+ logging.warning(error_msg)
118
+ yield error_msg
119
+ return
120
+
121
+ logging.info("Server is ready. Sending streaming request to AI model...")
122
+
123
+ # Send streaming request
124
+ response = self.client.chat.completions.create(
125
+ model="DavidAU/OpenAi-GPT-oss-20b-abliterated-uncensored-NEO-Imatrix-gguf",
126
+ messages=[
127
+ {"role": "system", "content": "You are a helpful research assistant that provides structured, analytical responses."},
128
+ {"role": "user", "content": prompt}
129
+ ],
130
+ temperature=0.7,
131
+ max_tokens=1500,
132
+ stream=True # Enable streaming
133
+ )
134
+
135
+ # Yield chunks as they arrive
136
+ for chunk in response:
137
+ if chunk.choices[0].delta.content:
138
+ yield chunk.choices[0].delta.content
139
+
140
+ logging.info("Analysis streaming completed successfully")
141
+
142
+ except Exception as e:
143
+ error_msg = str(e)
144
+ logging.error(f"Analysis streaming failed: {error_msg}")
145
+ if "503" in error_msg or "Service Unavailable" in error_msg:
146
+ yield "⚠️ The AI model server is currently unavailable. It may be initializing. Please try again in a few minutes."
147
+ elif "timeout" in error_msg.lower() or "read timeout" in error_msg.lower():
148
+ yield "⚠️ The AI model request timed out. The server may be overloaded or initializing. Please try again in a few minutes."
149
+ elif "404" in error_msg:
150
+ yield "⚠️ The AI model endpoint was not found. Please check the configuration."
151
+ else:
152
+ yield f"Analysis failed: {str(e)}"
153
+
154
  def analyze(self, query, search_results):
155
  """
156
+ Non-streaming version for compatibility
157
  """
158
  # Prepare context from search results
159
  context = "\n\n".join([