File size: 6,450 Bytes
1d8ffcd
eb339cc
b97f2de
e76df21
38fca59
a07c74e
e334d2d
 
e76df21
6319943
 
4839c34
6319943
51835ea
 
 
 
827ac99
51835ea
827ac99
 
 
51835ea
 
 
 
38fca59
6319943
 
38fca59
 
6319943
 
38fca59
 
6319943
38fca59
6319943
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47f482b
 
b337a43
51835ea
6319943
 
4839c34
 
 
 
827ac99
 
 
 
 
 
4839c34
 
6319943
 
 
b337a43
 
226d94f
 
1d8ffcd
4ec2867
b337a43
226d94f
51835ea
a0aaa8e
6319943
51835ea
6319943
 
38fca59
a0aaa8e
 
 
 
38fca59
a0aaa8e
b97f2de
47f482b
6319943
 
 
0b60a18
6319943
 
47f482b
 
a07c74e
 
 
 
9b69859
1d8ffcd
a07c74e
 
 
970276b
 
 
 
 
 
47f482b
 
226d94f
970276b
9b69859
a07c74e
47f482b
 
4ffcfc1
970276b
6319943
cd1cb3b
970276b
a07c74e
51835ea
827ac99
6319943
 
 
 
 
 
 
 
 
 
 
 
a07c74e
47f482b
9b69859
6319943
 
226d94f
a07c74e
cd1cb3b
6319943
970276b
 
a63edd5
eb339cc
6319943
 
 
226d94f
a07c74e
 
1d8ffcd
 
a07c74e
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
"""qResearch: Dual-Agent Research System"""

import os
import gradio as gr
from smolagents import CodeAgent, HfApiModel, tool
from typing import Dict, List, Optional, Tuple, Union
import requests
from urllib.parse import quote_plus

# Import browser components
from scripts.text_web_browser import SimpleTextBrowser, SearchInformationTool
from scripts.cookies import COOKIES

class DuckDuckGoSearchTool(SearchInformationTool):
    """Search tool that uses DuckDuckGo's HTML interface"""
    
    def forward(self, query: str, filter_year: Optional[int] = None) -> str:
        """Performs search using DuckDuckGo's HTML endpoint"""
        encoded_query = quote_plus(query)
        # Use the HTML endpoint directly
        url = f"https://html.duckduckgo.com/html/?q={encoded_query}"
        print(f"DEBUG: Searching with URL: {url}")
        self.browser.visit_page(url)
        header, content = self.browser._state()
        return header.strip() + "\n=======================\n" + content

@tool
def analyze_content(text: str, analysis_type: str = "general") -> str:
    """Analyzes content for various aspects like key points, themes, or citations
    
    Args:
        text: The content text to be analyzed for key points and themes
        analysis_type: Type of analysis to perform ("general", "academic", "citations")
    
    Returns:
        str: Structured analysis results including key points and findings
    """
    if "academic" in analysis_type.lower():
        return (
            "Academic Analysis:\n"
            "1. Main Arguments:\n"
            f"   - Key points from text: {text[:200]}...\n"
            "2. Evidence Quality:\n"
            "   - Source credibility assessment\n"
            "   - Data verification\n"
            "3. Research Context:\n"
            "   - Field relevance\n"
            "   - Current research status"
        )
    else:
        return (
            "General Analysis:\n"
            "1. Key Findings:\n"
            f"   - Main points from content: {text[:200]}...\n"
            "2. Supporting Evidence:\n"
            "   - Data and examples\n"
            "3. Practical Applications:\n"
            "   - Real-world relevance\n"
            "   - Implementation possibilities"
        )

class ResearchSystem:
    def __init__(self):
        # Initialize browser with request settings
        self.browser = SimpleTextBrowser(
            viewport_size=4096,
            downloads_folder="./downloads",
            request_kwargs={
                "cookies": COOKIES,
                "headers": {
                    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
                    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
                    "Accept-Language": "en-US,en;q=0.5",
                    "DNT": "1",
                    "Connection": "keep-alive",
                    "Upgrade-Insecure-Requests": "1"
                }
            }
        )
        
        # Initialize model
        self.model = HfApiModel(
            model_id="Qwen/Qwen2.5-Coder-32B-Instruct",
            custom_role_conversions={
                "tool-call": "assistant",
                "tool-response": "user"
            }
        )

        # Initialize agent with custom DuckDuckGo search tool
        self.researcher = CodeAgent(
            tools=[
                DuckDuckGoSearchTool(self.browser),
                analyze_content
            ],
            model=self.model
        )
        
        self.formatter = CodeAgent(
            tools=[],
            model=self.model
        )

    def create_interface(self):
        with gr.Blocks(title="qResearch", theme=gr.themes.Soft()) as interface:
            gr.Markdown(
                "# qResearch\n"
                "*Research → Analysis*\n"
                "---"
            )
            
            with gr.Row():
                with gr.Column(scale=3):
                    chat = gr.Chatbot(
                        label="Research Process",
                        height=600,
                        show_label=True,
                        type="messages"
                    )
                    
                with gr.Column(scale=1):
                    input_box = gr.Textbox(
                        label="Research Query",
                        placeholder="Enter your research topic...",
                        lines=3
                    )
                    submit_btn = gr.Button("Search", variant="primary")
            
            submit_btn.click(
                self.process_query,
                inputs=[input_box],
                outputs=[chat]
            )
        
        return interface

    def process_query(self, query: str) -> List[Dict[str, str]]:
        """Process a research query using web search and analysis"""
        try:
            print(f"\nDEBUG: Processing query: {query}")
            
            # Get search results using the browser
            search_results = self.researcher.run(f"Search for information about: {query}")
            print(f"\nDEBUG: Search completed. Results:\n{search_results}")
            
            # Analyze the results
            analysis = self.researcher.run(f"analyze_content: {search_results}")
            
            # Format in MLA style
            format_prompt = (
                "Format this research in MLA style:\n"
                f"{search_results}\n\n"
                f"Analysis:\n{analysis}"
            )
            formatted = self.formatter.run(format_prompt)
            
            return [
                {"role": "user", "content": query},
                {"role": "assistant", "content": f"📚 Research Findings:\n{search_results}\n\n📊 Analysis:\n{analysis}"},
                {"role": "assistant", "content": f"📝 MLA Formatted:\n{formatted}"}
            ]
            
        except Exception as e:
            error_msg = f"Error during research: {str(e)}"
            print(f"DEBUG: Error occurred: {error_msg}")
            return [{"role": "assistant", "content": error_msg}]

if __name__ == "__main__":
    # Create downloads directory if it doesn't exist
    os.makedirs("./downloads", exist_ok=True)
    
    system = ResearchSystem()
    system.create_interface().launch(
        server_port=7860,
        share=True,
        show_api=False
    )