[DOCS][FIX] [interactive group chat]

pull/864/merge
Kye Gomez 3 weeks ago
parent 86facfd32a
commit 1c36a1340e

@ -25,6 +25,7 @@ pip install swarms
Initializes a new InteractiveGroupChat instance with the specified configuration. Initializes a new InteractiveGroupChat instance with the specified configuration.
**Arguments:** **Arguments:**
| Parameter | Type | Description | Default | | Parameter | Type | Description | Default |
|-----------|------|-------------|---------| |-----------|------|-------------|---------|
| `id` | str | Unique identifier for the chat | auto-generated key | | `id` | str | Unique identifier for the chat | auto-generated key |
@ -36,6 +37,7 @@ Initializes a new InteractiveGroupChat instance with the specified configuration
| `interactive` | bool | Whether to enable interactive mode | False | | `interactive` | bool | Whether to enable interactive mode | False |
**Example:** **Example:**
```python ```python
from swarms import Agent, InteractiveGroupChat from swarms import Agent, InteractiveGroupChat

@ -5,13 +5,12 @@ import os
from concurrent.futures import ThreadPoolExecutor, as_completed from concurrent.futures import ThreadPoolExecutor, as_completed
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, Tuple from typing import Any, Dict, List
import aiohttp import aiohttp
from dotenv import load_dotenv from dotenv import load_dotenv
from rich.console import Console from rich.console import Console
from rich.panel import Panel from rich.panel import Panel
from rich.text import Text
from rich.tree import Tree from rich.tree import Tree
from swarms.agents.reasoning_duo import ReasoningDuo from swarms.agents.reasoning_duo import ReasoningDuo
@ -122,12 +121,12 @@ async def _async_exa_search(
) -> Dict[str, Any]: ) -> Dict[str, Any]:
"""Asynchronous helper function for Exa.ai API requests""" """Asynchronous helper function for Exa.ai API requests"""
api_url = "https://api.exa.ai/search" api_url = "https://api.exa.ai/search"
# Check if API key is available # Check if API key is available
api_key = os.getenv("EXA_API_KEY") api_key = os.getenv("EXA_API_KEY")
if not api_key: if not api_key:
return {"error": "EXA_API_KEY environment variable not set"} return {"error": "EXA_API_KEY environment variable not set"}
headers = { headers = {
"x-api-key": api_key, "x-api-key": api_key,
"Content-Type": "application/json", "Content-Type": "application/json",
@ -135,7 +134,8 @@ async def _async_exa_search(
# Filter out None keys AND None values from kwargs # Filter out None keys AND None values from kwargs
safe_kwargs = { safe_kwargs = {
str(k): v for k, v in kwargs.items() str(k): v
for k, v in kwargs.items()
if k is not None and v is not None and str(k) != "None" if k is not None and v is not None and str(k) != "None"
} }
@ -148,10 +148,15 @@ async def _async_exa_search(
"highlights": {"numSentences": 2}, "highlights": {"numSentences": 2},
}, },
} }
# Only add safe_kwargs if they don't conflict with existing keys # Only add safe_kwargs if they don't conflict with existing keys
for key, value in safe_kwargs.items(): for key, value in safe_kwargs.items():
if key not in payload and key not in ["query", "useAutoprompt", "numResults", "contents"]: if key not in payload and key not in [
"query",
"useAutoprompt",
"numResults",
"contents",
]:
payload[key] = value payload[key] = value
try: try:
@ -420,10 +425,14 @@ class DeepResearchSwarm:
try: try:
# Get all the queries to process # Get all the queries to process
queries = self.get_queries(query) queries = self.get_queries(query)
if not queries: if not queries:
error_msg = "No queries generated. Please check your input." error_msg = (
self.conversation.add(role="System", content=error_msg) "No queries generated. Please check your input."
)
self.conversation.add(
role="System", content=error_msg
)
return history_output_formatter( return history_output_formatter(
self.conversation, type=self.output_type self.conversation, type=self.output_type
) )
@ -448,7 +457,9 @@ class DeepResearchSwarm:
except Exception as e: except Exception as e:
# Handle any errors in the thread # Handle any errors in the thread
error_msg = f"Error processing query '{q}': {str(e)}" error_msg = (
f"Error processing query '{q}': {str(e)}"
)
console.print(f"[bold red]{error_msg}[/bold red]") console.print(f"[bold red]{error_msg}[/bold red]")
self.conversation.add( self.conversation.add(
role="System", role="System",
@ -466,7 +477,9 @@ class DeepResearchSwarm:
content=final_summary, content=final_summary,
) )
except Exception as e: except Exception as e:
error_msg = f"Error generating final summary: {str(e)}" error_msg = (
f"Error generating final summary: {str(e)}"
)
console.print(f"[bold red]{error_msg}[/bold red]") console.print(f"[bold red]{error_msg}[/bold red]")
self.conversation.add( self.conversation.add(
role="System", role="System",
@ -477,25 +490,32 @@ class DeepResearchSwarm:
result = history_output_formatter( result = history_output_formatter(
self.conversation, type=self.output_type self.conversation, type=self.output_type
) )
# If output type is JSON, ensure it's properly formatted # If output type is JSON, ensure it's properly formatted
if self.output_type.lower() == "json": if self.output_type.lower() == "json":
try: try:
import json import json
if isinstance(result, str): if isinstance(result, str):
# Try to parse and reformat for pretty printing # Try to parse and reformat for pretty printing
parsed = json.loads(result) parsed = json.loads(result)
return json.dumps(parsed, indent=2, ensure_ascii=False) return json.dumps(
parsed, indent=2, ensure_ascii=False
)
except (json.JSONDecodeError, TypeError): except (json.JSONDecodeError, TypeError):
# If parsing fails, return as-is # If parsing fails, return as-is
pass pass
return result return result
except Exception as e: except Exception as e:
error_msg = f"Critical error in step execution: {str(e)}" error_msg = f"Critical error in step execution: {str(e)}"
console.print(f"[bold red]{error_msg}[/bold red]") console.print(f"[bold red]{error_msg}[/bold red]")
return {"error": error_msg} if self.output_type.lower() == "json" else error_msg return (
{"error": error_msg}
if self.output_type.lower() == "json"
else error_msg
)
def run(self, task: str): def run(self, task: str):
return self.step(task) return self.step(task)
@ -515,10 +535,12 @@ class DeepResearchSwarm:
future = self.executor.submit(self.step, task) future = self.executor.submit(self.step, task)
futures.append((task, future)) futures.append((task, future))
def parse_and_display_results(self, json_result: str, export_markdown: bool = True): def parse_and_display_results(
self, json_result: str, export_markdown: bool = True
):
""" """
Parse JSON results and display in rich format with optional markdown export. Parse JSON results and display in rich format with optional markdown export.
Args: Args:
json_result (str): JSON string containing conversation results json_result (str): JSON string containing conversation results
export_markdown (bool): Whether to export to markdown file export_markdown (bool): Whether to export to markdown file
@ -526,86 +548,130 @@ class DeepResearchSwarm:
try: try:
# Parse JSON # Parse JSON
data = json.loads(json_result) data = json.loads(json_result)
# Create rich display # Create rich display
console.print("\n" + "="*100, style="cyan") console.print("\n" + "=" * 100, style="cyan")
console.print("🔬 DEEP RESEARCH RESULTS", style="bold cyan", justify="center") console.print(
console.print("="*100, style="cyan") "🔬 DEEP RESEARCH RESULTS",
style="bold cyan",
justify="center",
)
console.print("=" * 100, style="cyan")
# Create conversation tree # Create conversation tree
tree = Tree("🗣️ Research Conversation", style="bold blue") tree = Tree("🗣️ Research Conversation", style="bold blue")
markdown_content = ["# Deep Research Results\n", f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"] markdown_content = [
"# Deep Research Results\n",
f"**Generated:** {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n",
]
for i, entry in enumerate(data, 1): for i, entry in enumerate(data, 1):
if isinstance(entry, dict): if isinstance(entry, dict):
role = entry.get('role', 'Unknown') role = entry.get("role", "Unknown")
content = entry.get('content', '') content = entry.get("content", "")
timestamp = entry.get('timestamp', '') timestamp = entry.get("timestamp", "")
# Get role info for display # Get role info for display
role_info = self._get_role_display_info(role) role_info = self._get_role_display_info(role)
# Create tree branch # Create tree branch
branch_text = f"{role_info['emoji']} {role}" branch_text = f"{role_info['emoji']} {role}"
if timestamp: if timestamp:
time_part = timestamp.split()[-1] if ' ' in timestamp else timestamp[-8:] time_part = (
timestamp.split()[-1]
if " " in timestamp
else timestamp[-8:]
)
branch_text += f" ({time_part})" branch_text += f" ({time_part})"
branch = tree.add(branch_text, style=role_info['style']) branch = tree.add(
branch_text, style=role_info["style"]
)
# Add content preview to tree # Add content preview to tree
content_preview = content[:150] + "..." if len(content) > 150 else content content_preview = (
content_preview = content_preview.replace('\n', ' ') content[:150] + "..."
if len(content) > 150
else content
)
content_preview = content_preview.replace(
"\n", " "
)
branch.add(content_preview, style="dim") branch.add(content_preview, style="dim")
# Add to markdown # Add to markdown
markdown_content.append(f"\n## {i}. {role}") markdown_content.append(f"\n## {i}. {role}")
if timestamp: if timestamp:
markdown_content.append(f"**Timestamp:** {timestamp}") markdown_content.append(
f"**Timestamp:** {timestamp}"
)
markdown_content.append(f"\n{content}\n") markdown_content.append(f"\n{content}\n")
# Display full content for important entries # Display full content for important entries
if role.lower() in ['reasoning-agent-01'] and len(content) > 300: if (
console.print(f"\n📋 {role} Full Response:", style="bold green") role.lower() in ["reasoning-agent-01"]
console.print(Panel(content, border_style="green", title=f"{role} Analysis")) and len(content) > 300
):
console.print(
f"\n📋 {role} Full Response:",
style="bold green",
)
console.print(
Panel(
content,
border_style="green",
title=f"{role} Analysis",
)
)
# Display the tree # Display the tree
console.print(tree) console.print(tree)
# Export to markdown if requested # Export to markdown if requested
if export_markdown: if export_markdown:
# Create deepsearch_results directory # Create deepsearch_results directory
results_dir = Path("deepsearch_results") results_dir = Path("deepsearch_results")
results_dir.mkdir(exist_ok=True) results_dir.mkdir(exist_ok=True)
# Generate filename with timestamp # Generate filename with timestamp
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
filename = results_dir / f"research_results_{timestamp}.md" filename = (
results_dir / f"research_results_{timestamp}.md"
)
# Write markdown file # Write markdown file
with open(filename, 'w', encoding='utf-8') as f: with open(filename, "w", encoding="utf-8") as f:
f.write('\n'.join(markdown_content)) f.write("\n".join(markdown_content))
console.print(f"\n💾 Results exported to: {filename}", style="bold green") console.print(
f"\n💾 Results exported to: {filename}",
console.print("\n✅ Research analysis complete!", style="bold cyan") style="bold green",
)
console.print(
"\n✅ Research analysis complete!", style="bold cyan"
)
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
console.print(f"❌ Error parsing JSON: {e}", style="red") console.print(f"❌ Error parsing JSON: {e}", style="red")
except Exception as e: except Exception as e:
console.print(f"❌ Error displaying results: {e}", style="red") console.print(
f"❌ Error displaying results: {e}", style="red"
)
def _get_role_display_info(self, role: str) -> Dict[str, str]: def _get_role_display_info(self, role: str) -> Dict[str, str]:
"""Get display information for different conversation roles.""" """Get display information for different conversation roles."""
role_map = { role_map = {
"user": {"emoji": "👤", "style": "cyan"}, "user": {"emoji": "👤", "style": "cyan"},
"deep-research-agent": {"emoji": "🔍", "style": "blue"}, "deep-research-agent": {"emoji": "🔍", "style": "blue"},
"reasoning-agent-01": {"emoji": "🧠", "style": "magenta"}, "reasoning-agent-01": {"emoji": "🧠", "style": "magenta"},
"system": {"emoji": "⚙️", "style": "yellow"}, "system": {"emoji": "⚙️", "style": "yellow"},
} }
role_lower = role.lower() role_lower = role.lower()
return role_map.get(role_lower, {"emoji": "🤖", "style": "white"}) return role_map.get(
role_lower, {"emoji": "🤖", "style": "white"}
)
# Example usage # Example usage
@ -617,10 +683,10 @@ class DeepResearchSwarm:
# result = swarm.step( # result = swarm.step(
# "What is the active tariff situation with mexico? Only create 2 queries" # "What is the active tariff situation with mexico? Only create 2 queries"
# ) # )
# # Parse and display results in rich format with markdown export # # Parse and display results in rich format with markdown export
# swarm.parse_and_display_results(result, export_markdown=True) # swarm.parse_and_display_results(result, export_markdown=True)
# except Exception as e: # except Exception as e:
# print(f"Error running deep research swarm: {str(e)}") # print(f"Error running deep research swarm: {str(e)}")
# import traceback # import traceback

Loading…
Cancel
Save