Update app.py
Browse files
app.py
CHANGED
@@ -26,20 +26,15 @@ class ChutesClient:
|
|
26 |
"Content-Type": "application/json"
|
27 |
}
|
28 |
|
29 |
-
# Prepare the body
|
30 |
body = {
|
31 |
"model": kwargs.get("model", "openai/gpt-oss-20b"),
|
32 |
"messages": kwargs.get("messages", []),
|
33 |
-
"stream": False,
|
34 |
"max_tokens": kwargs.get("max_tokens", 1024),
|
35 |
"temperature": kwargs.get("temperature", 0.7)
|
36 |
}
|
37 |
|
38 |
-
# Add tool calls if present
|
39 |
-
if "tools" in kwargs and kwargs["tools"]:
|
40 |
-
body["tools"] = kwargs["tools"]
|
41 |
-
body["tool_choice"] = kwargs.get("tool_choice", "auto")
|
42 |
-
|
43 |
async with aiohttp.ClientSession() as session:
|
44 |
async with session.post(
|
45 |
f"{self.base_url}/chat/completions",
|
@@ -80,7 +75,7 @@ class CreativeAgenticAI:
|
|
80 |
self.available_models = {
|
81 |
"compound-beta": {"supports_web_search": True, "supports_browser_search": False, "api": "groq"},
|
82 |
"compound-beta-mini": {"supports_web_search": True, "supports_browser_search": False, "api": "groq"},
|
83 |
-
"openai/gpt-oss-20b": {"supports_web_search": False, "supports_browser_search":
|
84 |
}
|
85 |
|
86 |
async def chat(self, message: str,
|
@@ -125,7 +120,7 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
125 |
domain_context = f"\nAvoid searching these domains: {', '.join(exclude_domains)}. Search everywhere else on the web."
|
126 |
|
127 |
search_instruction = ""
|
128 |
-
if search_type == "browser_search":
|
129 |
search_instruction = "\nUse browser search tools to find the most current and relevant information from the web."
|
130 |
elif search_type == "web_search":
|
131 |
search_instruction = "\nUse web search capabilities to find relevant information."
|
@@ -147,11 +142,7 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
147 |
|
148 |
# Build messages
|
149 |
messages = [{"role": "system", "content": system_prompt}]
|
150 |
-
|
151 |
-
# Add conversation history (last 10 exchanges)
|
152 |
-
messages.extend(self.conversation_history[-20:]) # Last 10 user-assistant pairs
|
153 |
-
|
154 |
-
# Add current message with context
|
155 |
enhanced_message = message
|
156 |
if include_domains or exclude_domains:
|
157 |
filter_context = []
|
@@ -178,20 +169,13 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
178 |
if exclude_domains and exclude_domains[0].strip():
|
179 |
params["exclude_domains"] = [domain.strip() for domain in exclude_domains if domain.strip()]
|
180 |
|
181 |
-
# Add tools
|
182 |
tools = []
|
183 |
tool_choice = None
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
tool_choice = "required" if force_search else "auto"
|
188 |
-
elif search_type == "auto":
|
189 |
-
if self._supports_browser_search():
|
190 |
-
tools = [{"type": "browser_search"}]
|
191 |
tool_choice = "required" if force_search else "auto"
|
192 |
-
elif force_search and self._supports_browser_search():
|
193 |
-
tools = [{"type": "browser_search"}]
|
194 |
-
tool_choice = "required"
|
195 |
|
196 |
if tools:
|
197 |
params["tools"] = tools
|
@@ -201,14 +185,17 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
201 |
# Make the API call based on model
|
202 |
if self.available_models[self.model]["api"] == "chutes":
|
203 |
response = await self.chutes_client.chat_completions_create(**params)
|
|
|
|
|
|
|
204 |
else:
|
205 |
params["max_completion_tokens"] = params.pop("max_tokens", None)
|
206 |
response = self.groq_client.chat.completions.create(**params)
|
|
|
|
|
207 |
|
208 |
-
|
209 |
-
|
210 |
-
# Extract tool usage information and enhance it
|
211 |
-
tool_info = self._extract_tool_info(response)
|
212 |
|
213 |
# Process content to enhance citations
|
214 |
processed_content = self._enhance_citations(content, tool_info)
|
@@ -217,8 +204,7 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
217 |
self.conversation_history.append({"role": "user", "content": message})
|
218 |
self.conversation_history.append({"role": "assistant", "content": processed_content})
|
219 |
|
220 |
-
|
221 |
-
response_data = {
|
222 |
"content": processed_content,
|
223 |
"timestamp": datetime.now().isoformat(),
|
224 |
"model": self.model,
|
@@ -233,8 +219,6 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
233 |
}
|
234 |
}
|
235 |
|
236 |
-
return response_data
|
237 |
-
|
238 |
except Exception as e:
|
239 |
error_msg = f"Error: {str(e)}"
|
240 |
self.conversation_history.append({"role": "user", "content": message})
|
@@ -256,7 +240,7 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
256 |
"""Check if current model supports browser search tools"""
|
257 |
return self.available_models.get(self.model, {}).get("supports_browser_search", False)
|
258 |
|
259 |
-
def _extract_tool_info(self, response) -> Dict:
|
260 |
"""Extract tool usage information in a JSON serializable format"""
|
261 |
tool_info = {
|
262 |
"tools_used": [],
|
@@ -264,8 +248,8 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
264 |
"sources_found": []
|
265 |
}
|
266 |
|
267 |
-
#
|
268 |
-
if hasattr(response.choices[0].message, 'executed_tools'):
|
269 |
tools = response.choices[0].message.executed_tools
|
270 |
if tools:
|
271 |
for tool in tools:
|
@@ -273,31 +257,27 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
273 |
"tool_type": getattr(tool, "type", "unknown"),
|
274 |
"tool_name": getattr(tool, "name", "unknown"),
|
275 |
}
|
276 |
-
|
277 |
if hasattr(tool, "input"):
|
278 |
tool_input = str(tool.input)
|
279 |
tool_dict["input"] = tool_input
|
280 |
if "search" in tool_dict["tool_name"].lower():
|
281 |
tool_info["search_queries"].append(tool_input)
|
282 |
-
|
283 |
if hasattr(tool, "output"):
|
284 |
tool_output = str(tool.output)
|
285 |
tool_dict["output"] = tool_output
|
286 |
urls = self._extract_urls(tool_output)
|
287 |
tool_info["sources_found"].extend(urls)
|
288 |
-
|
289 |
tool_info["tools_used"].append(tool_dict)
|
290 |
|
291 |
-
#
|
292 |
-
if
|
293 |
-
for tool_call in
|
294 |
tool_dict = {
|
295 |
-
"tool_type":
|
296 |
-
"tool_name":
|
297 |
-
"tool_id":
|
298 |
}
|
299 |
-
|
300 |
-
if hasattr(tool_call, 'function') and hasattr(tool_call.function, 'arguments'):
|
301 |
try:
|
302 |
args = json.loads(tool_call.function.arguments) if isinstance(tool_call.function.arguments, str) else tool_call.function.arguments
|
303 |
tool_dict["arguments"] = args
|
@@ -305,7 +285,6 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
305 |
tool_info["search_queries"].append(args["query"])
|
306 |
except:
|
307 |
tool_dict["arguments"] = str(tool_call.function.arguments)
|
308 |
-
|
309 |
tool_info["tools_used"].append(tool_dict)
|
310 |
|
311 |
return tool_info
|
@@ -326,7 +305,6 @@ IMPORTANT: When you search the web and find information, you MUST:
|
|
326 |
for i, url in enumerate(tool_info["sources_found"][:10], 1):
|
327 |
domain = self._extract_domain(url)
|
328 |
sources_section += f"{i}. [{domain}]({url})\n"
|
329 |
-
|
330 |
content += sources_section
|
331 |
|
332 |
return content
|
@@ -378,7 +356,6 @@ async def validate_api_keys(groq_api_key: str, chutes_api_key: str, model: str)
|
|
378 |
return "β Please enter a valid Groq API key for the selected model"
|
379 |
|
380 |
try:
|
381 |
-
# Test API keys based on model
|
382 |
if model == "openai/gpt-oss-20b":
|
383 |
chutes_client = ChutesClient(api_key=chutes_api_key)
|
384 |
await chutes_client.chat_completions_create(
|
@@ -394,7 +371,6 @@ async def validate_api_keys(groq_api_key: str, chutes_api_key: str, model: str)
|
|
394 |
max_tokens=10
|
395 |
)
|
396 |
|
397 |
-
# Create AI instance
|
398 |
ai_instance = CreativeAgenticAI(groq_api_key=groq_api_key, chutes_api_key=chutes_api_key, model=model)
|
399 |
api_key_status = "Valid β
"
|
400 |
|
@@ -599,7 +575,7 @@ def create_gradio_app():
|
|
599 |
gr.HTML("""
|
600 |
<div class="header">
|
601 |
<h1>π€ NeuroScope-AI Enhanced</h1>
|
602 |
-
<p>Powered by Groq and Chutes Models with Web Search
|
603 |
</div>
|
604 |
""")
|
605 |
|
@@ -608,9 +584,9 @@ def create_gradio_app():
|
|
608 |
gr.Markdown("""
|
609 |
**Enhanced with Multiple Search Capabilities:**
|
610 |
- π§ **Intelligence** (Neuro): Advanced AI reasoning across multiple models
|
611 |
-
- π **Precision Search** (Scope): Domain filtering
|
612 |
- π€ **AI Capabilities** (AI): Agentic behavior with tool usage
|
613 |
-
- β‘ **Dual
|
614 |
- π― **Model Flexibility**: Choose the right model for your task
|
615 |
""")
|
616 |
|
@@ -627,10 +603,10 @@ def create_gradio_app():
|
|
627 |
<li><strong>Features:</strong> Include/exclude domains, autonomous web search</li>
|
628 |
</ul>
|
629 |
|
630 |
-
<h4
|
631 |
<ul>
|
632 |
-
<li><strong>openai/gpt-oss-20b:</strong> Fast
|
633 |
-
<li><strong>Features:</strong>
|
634 |
</ul>
|
635 |
</div>
|
636 |
|
@@ -638,10 +614,9 @@ def create_gradio_app():
|
|
638 |
<h3>π Enhanced Citation System</h3>
|
639 |
<p>All models now include:</p>
|
640 |
<ul>
|
641 |
-
<li><strong>Automatic Source Citations:</strong> Clickable links to sources</li>
|
642 |
<li><strong>Sources Used Section:</strong> Dedicated section showing all websites</li>
|
643 |
<li><strong>Search Type Indication:</strong> Shows which search method was used</li>
|
644 |
-
<li><strong>Tool Usage Display:</strong> Transparent about AI's research process</li>
|
645 |
</ul>
|
646 |
</div>
|
647 |
""")
|
@@ -669,7 +644,7 @@ def create_gradio_app():
|
|
669 |
],
|
670 |
label="π§ Model Selection",
|
671 |
value="compound-beta",
|
672 |
-
info="Choose based on your
|
673 |
)
|
674 |
with gr.Column(scale=1):
|
675 |
connect_btn = gr.Button("π Connect", variant="primary", size="lg")
|
@@ -710,7 +685,7 @@ def create_gradio_app():
|
|
710 |
with gr.Accordion("π Search Settings", open=False, elem_id="neuroscope-accordion"):
|
711 |
with gr.Row():
|
712 |
search_type = gr.Radio(
|
713 |
-
choices=["auto", "web_search", "
|
714 |
label="π― Search Type",
|
715 |
value="auto",
|
716 |
info="Choose search method (auto = model decides)"
|
@@ -718,7 +693,7 @@ def create_gradio_app():
|
|
718 |
force_search = gr.Checkbox(
|
719 |
label="β‘ Force Search",
|
720 |
value=False,
|
721 |
-
info="Force AI to search even for general questions"
|
722 |
)
|
723 |
|
724 |
model_selection.change(
|
@@ -788,18 +763,15 @@ def create_gradio_app():
|
|
788 |
- Best for: Research papers, academic sources, filtered searches
|
789 |
- API: Groq
|
790 |
|
791 |
-
**For Current Events & Real-Time Information:**
|
792 |
-
- `openai/gpt-oss-20b` with browser search
|
793 |
-
- Best for: News, current events, real-time data
|
794 |
-
- API: Chutes
|
795 |
-
|
796 |
**For General Knowledge & Creative Tasks:**
|
797 |
-
-
|
798 |
-
- Best for: Creative writing, general questions
|
|
|
799 |
|
800 |
**For Programming & Technical Documentation:**
|
801 |
-
- `
|
802 |
- Best for: Code help, documentation, technical guides
|
|
|
803 |
""")
|
804 |
|
805 |
with gr.Accordion("π Common Domain Examples", open=False, elem_id="neuroscope-accordion"):
|
@@ -827,20 +799,19 @@ def create_gradio_app():
|
|
827 |
gr.Markdown("""
|
828 |
### π Getting Started
|
829 |
1. **Enter your API Keys** - Groq from [console.groq.com](https://console.groq.com/), Chutes for openai/gpt-oss-20b
|
830 |
-
2. **Select a model** - Choose based on your
|
831 |
- **Compound models** (Groq): For web search with domain filtering
|
832 |
-
- **openai/gpt-oss-20b** (Chutes): For
|
833 |
-
3. **Configure search settings** - Choose search type and options
|
834 |
4. **Click Connect** - Validate your keys and connect to the AI
|
835 |
5. **Start chatting!** - Type your message and get intelligent responses with citations
|
836 |
|
837 |
### π― Key Features
|
838 |
-
- **Dual
|
839 |
-
- **Smart Citations**: Automatic source linking and citation formatting
|
840 |
-
- **Domain Filtering**: Control which websites the AI searches (
|
841 |
-
- **Real-time Search**: Get current information with browser search tools
|
842 |
- **Model Flexibility**: Choose the right model and API for your task
|
843 |
-
- **Enhanced Tool Visibility**: See
|
844 |
|
845 |
### π‘ Tips for Best Results
|
846 |
|
@@ -849,13 +820,8 @@ def create_gradio_app():
|
|
849 |
- Include academic domains (*.edu, arxiv.org) for scholarly sources
|
850 |
- Use "Force Search" for the most current information
|
851 |
|
852 |
-
**For Current Events:**
|
853 |
-
- Use openai/gpt-oss-20b (Chutes)
|
854 |
-
- Set search type to "browser_search"
|
855 |
-
- Enable "Force Search" for real-time data
|
856 |
-
|
857 |
**For Creative Tasks:**
|
858 |
-
-
|
859 |
- Set search type to "none" for purely creative responses
|
860 |
- Use higher temperature (0.8-1.0) for more creativity
|
861 |
""")
|
@@ -863,7 +829,7 @@ def create_gradio_app():
|
|
863 |
with gr.Accordion("π― Sample Examples to Test Enhanced Search", open=False, elem_id="neuroscope-accordion"):
|
864 |
gr.Markdown("""
|
865 |
<div class="example-box">
|
866 |
-
<h4>π¬ Research & Analysis
|
867 |
|
868 |
**Compound Model + Domain Filtering (Groq):**
|
869 |
- Query: "What are the latest breakthroughs in quantum computing?"
|
@@ -871,48 +837,35 @@ def create_gradio_app():
|
|
871 |
- Include domains: "arxiv.org, *.edu, nature.com"
|
872 |
- Search type: web_search
|
873 |
|
874 |
-
|
875 |
-
-
|
876 |
-
-
|
877 |
-
-
|
878 |
-
|
879 |
-
<h4>π° Current Events (Browser Search Excellence)</h4>
|
880 |
|
881 |
-
|
882 |
-
- Query: "What happened in AI industry this week?"
|
883 |
-
- Model: openai/gpt-oss-20b (Chutes)
|
884 |
-
- Search type: browser_search
|
885 |
-
- Force search: enabled
|
886 |
|
887 |
-
**
|
888 |
-
- Same query with compound-beta (Groq)
|
889 |
-
- Include domains: "reuters.com, bbc.com, techcrunch.com"
|
890 |
-
|
891 |
-
<h4>π» Programming & Tech (Model Comparison)</h4>
|
892 |
-
|
893 |
-
**Technical Documentation:**
|
894 |
- Query: "How to implement OAuth 2.0 in Python Flask?"
|
895 |
-
-
|
896 |
-
|
897 |
-
|
|
|
|
|
|
|
|
|
898 |
|
899 |
-
<h4>π¨ Creative Tasks
|
900 |
- Query: "Write a short story about AI and humans working together"
|
901 |
- Any model with search_type: "none"
|
902 |
- Higher temperature (0.8-1.0)
|
903 |
|
904 |
-
<h4>π Business Analysis
|
905 |
|
906 |
-
**
|
907 |
-
- Query: "Current cryptocurrency market trends"
|
908 |
-
- Model: openai/gpt-oss-20b (Chutes)
|
909 |
-
- Search type: browser_search
|
910 |
-
- Force search: enabled
|
911 |
-
|
912 |
-
**Business Analysis (Filtered):**
|
913 |
- Query: "Cryptocurrency adoption in enterprise"
|
914 |
-
- Model: compound-beta
|
915 |
- Include domains: "bloomberg.com, wsj.com, harvard.edu"
|
|
|
916 |
</div>
|
917 |
""")
|
918 |
|
@@ -935,29 +888,28 @@ def create_gradio_app():
|
|
935 |
|
936 |
with gr.Accordion("π About This Enhanced NeuroScope AI", open=True, elem_id="neuroscope-accordion"):
|
937 |
gr.Markdown("""
|
938 |
-
**Enhanced Creative Agentic AI Chat Tool** with dual
|
939 |
|
940 |
### π **New in This Version:**
|
941 |
-
-
|
942 |
-
- π **Dual
|
943 |
- π― **Model Flexibility**: Multiple models across two APIs
|
944 |
-
- β‘ **Force Search Option**: Make AI search
|
945 |
-
- π§ **Enhanced Tool Visibility**: See
|
946 |
-
- π **Model Comparison Guide**: Choose the right model and API
|
947 |
|
948 |
### π **Core Features:**
|
949 |
-
- π **Automatic Source Citations**:
|
950 |
-
- π **Sources Used Section**: Dedicated section
|
951 |
-
- π **Smart Domain Filtering**: Control search scope (
|
952 |
-
- π **Real-time Browser Search**: Current information (Chutes model)
|
953 |
- π¬ **Conversational Memory**: Maintains context throughout the session
|
954 |
- βοΈ **Full Customization**: Adjust all parameters and prompts
|
955 |
- π¨ **Creative & Analytical**: Optimized for both creative and research tasks
|
956 |
|
957 |
### π οΈ **Technical Details:**
|
958 |
- **Compound Models (Groq)**: compound-beta, compound-beta-mini (web search + domain filtering)
|
959 |
-
- **
|
960 |
-
- **Automatic Search Type Detection**: AI chooses best search method
|
961 |
- **Enhanced Error Handling**: Robust error management and user feedback
|
962 |
- **Real-time Status Updates**: Live feedback on model capabilities and search settings
|
963 |
""")
|
@@ -968,5 +920,7 @@ def create_gradio_app():
|
|
968 |
if __name__ == "__main__":
|
969 |
app = create_gradio_app()
|
970 |
app.launch(
|
971 |
-
share=True
|
|
|
|
|
972 |
)
|
|
|
26 |
"Content-Type": "application/json"
|
27 |
}
|
28 |
|
29 |
+
# Prepare the body, excluding tools since Chutes doesn't support the same format
|
30 |
body = {
|
31 |
"model": kwargs.get("model", "openai/gpt-oss-20b"),
|
32 |
"messages": kwargs.get("messages", []),
|
33 |
+
"stream": False,
|
34 |
"max_tokens": kwargs.get("max_tokens", 1024),
|
35 |
"temperature": kwargs.get("temperature", 0.7)
|
36 |
}
|
37 |
|
|
|
|
|
|
|
|
|
|
|
38 |
async with aiohttp.ClientSession() as session:
|
39 |
async with session.post(
|
40 |
f"{self.base_url}/chat/completions",
|
|
|
75 |
self.available_models = {
|
76 |
"compound-beta": {"supports_web_search": True, "supports_browser_search": False, "api": "groq"},
|
77 |
"compound-beta-mini": {"supports_web_search": True, "supports_browser_search": False, "api": "groq"},
|
78 |
+
"openai/gpt-oss-20b": {"supports_web_search": False, "supports_browser_search": False, "api": "chutes"},
|
79 |
}
|
80 |
|
81 |
async def chat(self, message: str,
|
|
|
120 |
domain_context = f"\nAvoid searching these domains: {', '.join(exclude_domains)}. Search everywhere else on the web."
|
121 |
|
122 |
search_instruction = ""
|
123 |
+
if search_type == "browser_search" and self._supports_browser_search():
|
124 |
search_instruction = "\nUse browser search tools to find the most current and relevant information from the web."
|
125 |
elif search_type == "web_search":
|
126 |
search_instruction = "\nUse web search capabilities to find relevant information."
|
|
|
142 |
|
143 |
# Build messages
|
144 |
messages = [{"role": "system", "content": system_prompt}]
|
145 |
+
messages.extend(self.conversation_history[-20:])
|
|
|
|
|
|
|
|
|
146 |
enhanced_message = message
|
147 |
if include_domains or exclude_domains:
|
148 |
filter_context = []
|
|
|
169 |
if exclude_domains and exclude_domains[0].strip():
|
170 |
params["exclude_domains"] = [domain.strip() for domain in exclude_domains if domain.strip()]
|
171 |
|
172 |
+
# Add tools only for Groq models that support browser search
|
173 |
tools = []
|
174 |
tool_choice = None
|
175 |
+
if self._supports_browser_search():
|
176 |
+
if search_type in ["browser_search", "auto"] or force_search:
|
177 |
+
tools = [{"type": "browser_search", "function": {"name": "browser_search"}}]
|
|
|
|
|
|
|
|
|
178 |
tool_choice = "required" if force_search else "auto"
|
|
|
|
|
|
|
179 |
|
180 |
if tools:
|
181 |
params["tools"] = tools
|
|
|
185 |
# Make the API call based on model
|
186 |
if self.available_models[self.model]["api"] == "chutes":
|
187 |
response = await self.chutes_client.chat_completions_create(**params)
|
188 |
+
# Handle Chutes response
|
189 |
+
content = response.get("choices", [{}])[0].get("message", {}).get("content", "No response content")
|
190 |
+
tool_calls = response.get("choices", [{}])[0].get("message", {}).get("tool_calls", None)
|
191 |
else:
|
192 |
params["max_completion_tokens"] = params.pop("max_tokens", None)
|
193 |
response = self.groq_client.chat.completions.create(**params)
|
194 |
+
content = response.choices[0].message.content
|
195 |
+
tool_calls = response.choices[0].message.tool_calls if hasattr(response.choices[0].message, "tool_calls") else None
|
196 |
|
197 |
+
# Extract tool usage information
|
198 |
+
tool_info = self._extract_tool_info(response, tool_calls)
|
|
|
|
|
199 |
|
200 |
# Process content to enhance citations
|
201 |
processed_content = self._enhance_citations(content, tool_info)
|
|
|
204 |
self.conversation_history.append({"role": "user", "content": message})
|
205 |
self.conversation_history.append({"role": "assistant", "content": processed_content})
|
206 |
|
207 |
+
return {
|
|
|
208 |
"content": processed_content,
|
209 |
"timestamp": datetime.now().isoformat(),
|
210 |
"model": self.model,
|
|
|
219 |
}
|
220 |
}
|
221 |
|
|
|
|
|
222 |
except Exception as e:
|
223 |
error_msg = f"Error: {str(e)}"
|
224 |
self.conversation_history.append({"role": "user", "content": message})
|
|
|
240 |
"""Check if current model supports browser search tools"""
|
241 |
return self.available_models.get(self.model, {}).get("supports_browser_search", False)
|
242 |
|
243 |
+
def _extract_tool_info(self, response, tool_calls) -> Dict:
|
244 |
"""Extract tool usage information in a JSON serializable format"""
|
245 |
tool_info = {
|
246 |
"tools_used": [],
|
|
|
248 |
"sources_found": []
|
249 |
}
|
250 |
|
251 |
+
# Handle Groq executed_tools
|
252 |
+
if hasattr(response, 'choices') and hasattr(response.choices[0].message, 'executed_tools'):
|
253 |
tools = response.choices[0].message.executed_tools
|
254 |
if tools:
|
255 |
for tool in tools:
|
|
|
257 |
"tool_type": getattr(tool, "type", "unknown"),
|
258 |
"tool_name": getattr(tool, "name", "unknown"),
|
259 |
}
|
|
|
260 |
if hasattr(tool, "input"):
|
261 |
tool_input = str(tool.input)
|
262 |
tool_dict["input"] = tool_input
|
263 |
if "search" in tool_dict["tool_name"].lower():
|
264 |
tool_info["search_queries"].append(tool_input)
|
|
|
265 |
if hasattr(tool, "output"):
|
266 |
tool_output = str(tool.output)
|
267 |
tool_dict["output"] = tool_output
|
268 |
urls = self._extract_urls(tool_output)
|
269 |
tool_info["sources_found"].extend(urls)
|
|
|
270 |
tool_info["tools_used"].append(tool_dict)
|
271 |
|
272 |
+
# Handle tool_calls for both APIs
|
273 |
+
if tool_calls:
|
274 |
+
for tool_call in tool_calls:
|
275 |
tool_dict = {
|
276 |
+
"tool_type": getattr(tool_call, "type", "browser_search"),
|
277 |
+
"tool_name": getattr(tool_call, "function", {}).get("name", "browser_search"),
|
278 |
+
"tool_id": getattr(tool_call, "id", None)
|
279 |
}
|
280 |
+
if hasattr(tool_call, "function") and hasattr(tool_call.function, "arguments"):
|
|
|
281 |
try:
|
282 |
args = json.loads(tool_call.function.arguments) if isinstance(tool_call.function.arguments, str) else tool_call.function.arguments
|
283 |
tool_dict["arguments"] = args
|
|
|
285 |
tool_info["search_queries"].append(args["query"])
|
286 |
except:
|
287 |
tool_dict["arguments"] = str(tool_call.function.arguments)
|
|
|
288 |
tool_info["tools_used"].append(tool_dict)
|
289 |
|
290 |
return tool_info
|
|
|
305 |
for i, url in enumerate(tool_info["sources_found"][:10], 1):
|
306 |
domain = self._extract_domain(url)
|
307 |
sources_section += f"{i}. [{domain}]({url})\n"
|
|
|
308 |
content += sources_section
|
309 |
|
310 |
return content
|
|
|
356 |
return "β Please enter a valid Groq API key for the selected model"
|
357 |
|
358 |
try:
|
|
|
359 |
if model == "openai/gpt-oss-20b":
|
360 |
chutes_client = ChutesClient(api_key=chutes_api_key)
|
361 |
await chutes_client.chat_completions_create(
|
|
|
371 |
max_tokens=10
|
372 |
)
|
373 |
|
|
|
374 |
ai_instance = CreativeAgenticAI(groq_api_key=groq_api_key, chutes_api_key=chutes_api_key, model=model)
|
375 |
api_key_status = "Valid β
"
|
376 |
|
|
|
575 |
gr.HTML("""
|
576 |
<div class="header">
|
577 |
<h1>π€ NeuroScope-AI Enhanced</h1>
|
578 |
+
<p>Powered by Groq and Chutes Models with Web Search and Agentic Capabilities</p>
|
579 |
</div>
|
580 |
""")
|
581 |
|
|
|
584 |
gr.Markdown("""
|
585 |
**Enhanced with Multiple Search Capabilities:**
|
586 |
- π§ **Intelligence** (Neuro): Advanced AI reasoning across multiple models
|
587 |
+
- π **Precision Search** (Scope): Domain filtering (Groq models)
|
588 |
- π€ **AI Capabilities** (AI): Agentic behavior with tool usage
|
589 |
+
- β‘ **Dual APIs**: Web search (Groq) + Basic chat (Chutes)
|
590 |
- π― **Model Flexibility**: Choose the right model for your task
|
591 |
""")
|
592 |
|
|
|
603 |
<li><strong>Features:</strong> Include/exclude domains, autonomous web search</li>
|
604 |
</ul>
|
605 |
|
606 |
+
<h4>π¬ Chat Model (Chutes API)</h4>
|
607 |
<ul>
|
608 |
+
<li><strong>openai/gpt-oss-20b:</strong> Fast conversational capabilities</li>
|
609 |
+
<li><strong>Features:</strong> General chat, no browser search</li>
|
610 |
</ul>
|
611 |
</div>
|
612 |
|
|
|
614 |
<h3>π Enhanced Citation System</h3>
|
615 |
<p>All models now include:</p>
|
616 |
<ul>
|
617 |
+
<li><strong>Automatic Source Citations:</strong> Clickable links to sources (Groq models)</li>
|
618 |
<li><strong>Sources Used Section:</strong> Dedicated section showing all websites</li>
|
619 |
<li><strong>Search Type Indication:</strong> Shows which search method was used</li>
|
|
|
620 |
</ul>
|
621 |
</div>
|
622 |
""")
|
|
|
644 |
],
|
645 |
label="π§ Model Selection",
|
646 |
value="compound-beta",
|
647 |
+
info="Choose based on your needs"
|
648 |
)
|
649 |
with gr.Column(scale=1):
|
650 |
connect_btn = gr.Button("π Connect", variant="primary", size="lg")
|
|
|
685 |
with gr.Accordion("π Search Settings", open=False, elem_id="neuroscope-accordion"):
|
686 |
with gr.Row():
|
687 |
search_type = gr.Radio(
|
688 |
+
choices=["auto", "web_search", "none"],
|
689 |
label="π― Search Type",
|
690 |
value="auto",
|
691 |
info="Choose search method (auto = model decides)"
|
|
|
693 |
force_search = gr.Checkbox(
|
694 |
label="β‘ Force Search",
|
695 |
value=False,
|
696 |
+
info="Force AI to search even for general questions (Groq models only)"
|
697 |
)
|
698 |
|
699 |
model_selection.change(
|
|
|
763 |
- Best for: Research papers, academic sources, filtered searches
|
764 |
- API: Groq
|
765 |
|
|
|
|
|
|
|
|
|
|
|
766 |
**For General Knowledge & Creative Tasks:**
|
767 |
+
- `openai/gpt-oss-20b` for fast conversational responses
|
768 |
+
- Best for: Creative writing, general questions
|
769 |
+
- API: Chutes
|
770 |
|
771 |
**For Programming & Technical Documentation:**
|
772 |
+
- `compound-beta` with tech domains
|
773 |
- Best for: Code help, documentation, technical guides
|
774 |
+
- API: Groq
|
775 |
""")
|
776 |
|
777 |
with gr.Accordion("π Common Domain Examples", open=False, elem_id="neuroscope-accordion"):
|
|
|
799 |
gr.Markdown("""
|
800 |
### π Getting Started
|
801 |
1. **Enter your API Keys** - Groq from [console.groq.com](https://console.groq.com/), Chutes for openai/gpt-oss-20b
|
802 |
+
2. **Select a model** - Choose based on your needs:
|
803 |
- **Compound models** (Groq): For web search with domain filtering
|
804 |
+
- **openai/gpt-oss-20b** (Chutes): For general conversational tasks
|
805 |
+
3. **Configure search settings** - Choose search type and options (Groq models only)
|
806 |
4. **Click Connect** - Validate your keys and connect to the AI
|
807 |
5. **Start chatting!** - Type your message and get intelligent responses with citations
|
808 |
|
809 |
### π― Key Features
|
810 |
+
- **Dual APIs**: Web search (Groq) + Basic chat (Chutes)
|
811 |
+
- **Smart Citations**: Automatic source linking and citation formatting (Groq models)
|
812 |
+
- **Domain Filtering**: Control which websites the AI searches (Groq models)
|
|
|
813 |
- **Model Flexibility**: Choose the right model and API for your task
|
814 |
+
- **Enhanced Tool Visibility**: See search tools used (Groq models)
|
815 |
|
816 |
### π‘ Tips for Best Results
|
817 |
|
|
|
820 |
- Include academic domains (*.edu, arxiv.org) for scholarly sources
|
821 |
- Use "Force Search" for the most current information
|
822 |
|
|
|
|
|
|
|
|
|
|
|
823 |
**For Creative Tasks:**
|
824 |
+
- Use openai/gpt-oss-20b (Chutes) or any model
|
825 |
- Set search type to "none" for purely creative responses
|
826 |
- Use higher temperature (0.8-1.0) for more creativity
|
827 |
""")
|
|
|
829 |
with gr.Accordion("π― Sample Examples to Test Enhanced Search", open=False, elem_id="neuroscope-accordion"):
|
830 |
gr.Markdown("""
|
831 |
<div class="example-box">
|
832 |
+
<h4>π¬ Research & Analysis</h4>
|
833 |
|
834 |
**Compound Model + Domain Filtering (Groq):**
|
835 |
- Query: "What are the latest breakthroughs in quantum computing?"
|
|
|
837 |
- Include domains: "arxiv.org, *.edu, nature.com"
|
838 |
- Search type: web_search
|
839 |
|
840 |
+
<h4>π¬ General Knowledge (Chutes):**
|
841 |
+
- Query: "Tell me about quantum computing"
|
842 |
+
- Model: openai/gpt-oss-20b
|
843 |
+
- Search type: none
|
|
|
|
|
844 |
|
845 |
+
<h4>π» Programming & Tech</h4>
|
|
|
|
|
|
|
|
|
846 |
|
847 |
+
**Technical Documentation (Groq):**
|
|
|
|
|
|
|
|
|
|
|
|
|
848 |
- Query: "How to implement OAuth 2.0 in Python Flask?"
|
849 |
+
- Model: compound-beta
|
850 |
+
- Include domains: "github.com, docs.python.org, stackoverflow.com"
|
851 |
+
- Search type: web_search
|
852 |
+
|
853 |
+
**Code Help (Chutes):**
|
854 |
+
- Same query with openai/gpt-oss-20b
|
855 |
+
- Search type: none
|
856 |
|
857 |
+
<h4>π¨ Creative Tasks</h4>
|
858 |
- Query: "Write a short story about AI and humans working together"
|
859 |
- Any model with search_type: "none"
|
860 |
- Higher temperature (0.8-1.0)
|
861 |
|
862 |
+
<h4>π Business Analysis</h4>
|
863 |
|
864 |
+
**Business Analysis (Filtered, Groq):**
|
|
|
|
|
|
|
|
|
|
|
|
|
865 |
- Query: "Cryptocurrency adoption in enterprise"
|
866 |
+
- Model: compound-beta
|
867 |
- Include domains: "bloomberg.com, wsj.com, harvard.edu"
|
868 |
+
- Search type: web_search
|
869 |
</div>
|
870 |
""")
|
871 |
|
|
|
888 |
|
889 |
with gr.Accordion("π About This Enhanced NeuroScope AI", open=True, elem_id="neuroscope-accordion"):
|
890 |
gr.Markdown("""
|
891 |
+
**Enhanced Creative Agentic AI Chat Tool** with dual API support:
|
892 |
|
893 |
### π **New in This Version:**
|
894 |
+
- π¬ **Chutes API Integration**: For openai/gpt-oss-20b model
|
895 |
+
- π **Dual API System**: Web search (Groq) + Basic chat (Chutes)
|
896 |
- π― **Model Flexibility**: Multiple models across two APIs
|
897 |
+
- β‘ **Force Search Option**: Make AI search for Groq models
|
898 |
+
- π§ **Enhanced Tool Visibility**: See search tools used (Groq models)
|
899 |
+
- π **Model Comparison Guide**: Choose the right model and API
|
900 |
|
901 |
### π **Core Features:**
|
902 |
+
- π **Automatic Source Citations**: Clickable links to sources (Groq models)
|
903 |
+
- π **Sources Used Section**: Dedicated section for websites (Groq models)
|
904 |
+
- π **Smart Domain Filtering**: Control search scope (Groq models)
|
|
|
905 |
- π¬ **Conversational Memory**: Maintains context throughout the session
|
906 |
- βοΈ **Full Customization**: Adjust all parameters and prompts
|
907 |
- π¨ **Creative & Analytical**: Optimized for both creative and research tasks
|
908 |
|
909 |
### π οΈ **Technical Details:**
|
910 |
- **Compound Models (Groq)**: compound-beta, compound-beta-mini (web search + domain filtering)
|
911 |
+
- **Chat Model (Chutes)**: openai/gpt-oss-20b (basic conversational capabilities)
|
912 |
+
- **Automatic Search Type Detection**: AI chooses best search method (Groq models)
|
913 |
- **Enhanced Error Handling**: Robust error management and user feedback
|
914 |
- **Real-time Status Updates**: Live feedback on model capabilities and search settings
|
915 |
""")
|
|
|
920 |
if __name__ == "__main__":
|
921 |
app = create_gradio_app()
|
922 |
app.launch(
|
923 |
+
share=True,
|
924 |
+
server_name="0.0.0.0",
|
925 |
+
server_port=7860
|
926 |
)
|