diff --git a/backend/server.py b/backend/server.py index 55d8a3db7..7167044d2 100644 --- a/backend/server.py +++ b/backend/server.py @@ -77,6 +77,7 @@ async def websocket_endpoint(websocket: WebSocket): json_data = json.loads(data[6:]) task = json_data.get("task") report_type = json_data.get("report_type") + source_urls = json_data.get("source_urls") tone = json_data.get("tone") headers = json_data.get("headers", {}) filename = f"task_{int(time.time())}_{task}" @@ -86,7 +87,7 @@ async def websocket_endpoint(websocket: WebSocket): report_source = json_data.get("report_source") if task and report_type: report = await manager.start_streaming( - task, report_type, report_source, tone, websocket, headers + task, report_type, report_source, source_urls, tone, websocket, headers ) # Ensure report is a string if not isinstance(report, str): diff --git a/backend/websocket_manager.py b/backend/websocket_manager.py index 0f47e6fe1..2c5287ff0 100644 --- a/backend/websocket_manager.py +++ b/backend/websocket_manager.py @@ -54,14 +54,14 @@ async def disconnect(self, websocket: WebSocket): del self.message_queues[websocket] - async def start_streaming(self, task, report_type, report_source, tone, websocket, headers=None): + async def start_streaming(self, task, report_type, report_source, source_urls, tone, websocket, headers=None): """Start streaming the output.""" tone = Tone[tone] - report = await run_agent(task, report_type, report_source, tone, websocket, headers) + report = await run_agent(task, report_type, report_source, source_urls, tone, websocket, headers) return report -async def run_agent(task, report_type, report_source, tone: Tone, websocket, headers=None): +async def run_agent(task, report_type, report_source, source_urls, tone: Tone, websocket, headers=None): """Run the agent.""" # measure time start_time = datetime.datetime.now() @@ -76,7 +76,7 @@ async def run_agent(task, report_type, report_source, tone: Tone, websocket, hea query=task, report_type=report_type, report_source=report_source, - source_urls=None, + source_urls=source_urls, tone=tone, config_path=config_path, websocket=websocket, @@ -88,14 +88,14 @@ async def run_agent(task, report_type, report_source, tone: Tone, websocket, hea query=task, report_type=report_type, report_source=report_source, - source_urls=None, + source_urls=source_urls, tone=tone, config_path=config_path, websocket=websocket, headers=headers ) report = await researcher.run() - + # measure time end_time = datetime.datetime.now() await websocket.send_json( diff --git a/frontend/index.html b/frontend/index.html index ec1b30bb9..c31e0960d 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -179,7 +179,19 @@

Research Report

autoAgentDiv.style.display = 'flex'; agentChoices[0].style.display = 'none'; }); - + + const tagsInput = document.getElementById('tags-input'); + const input = document.getElementById('custom_source'); + + input.addEventListener('keypress', function (e) { + if ((e.key === 'Enter' || e.key === ",") && input.value !== '') { + e.preventDefault(); + GPTResearcher.addTag(input.value); + input.value = ''; + } + }); + + \ No newline at end of file diff --git a/frontend/scripts.js b/frontend/scripts.js index 23a75cdd7..614c737ef 100644 --- a/frontend/scripts.js +++ b/frontend/scripts.js @@ -9,6 +9,15 @@ const GPTResearcher = (() => { updateState('initial') } + const changeSource = () => { + const report_source = document.querySelector('select[name="report_source"]').value + if (report_source === 'sources') { + document.getElementById('sources').style.display = 'block' + } else { + document.getElementById('sources').style.display = 'none' + } + } + const startResearch = () => { document.getElementById('output').innerHTML = '' document.getElementById('reportContainer').innerHTML = '' @@ -51,11 +60,17 @@ const GPTResearcher = (() => { ).value const tone = document.querySelector('select[name="tone"]').value const agent = document.querySelector('input[name="agent"]:checked').value + let source_urls = tags + + if (report_source !== 'sources' && source_urls.length > 0) { + source_urls = source_urls.slice(0, source_urls.length - 1) + } const requestData = { task: task, report_type: report_type, report_source: report_source, + source_urls: source_urls, tone: tone, agent: agent, } @@ -159,9 +174,36 @@ const GPTResearcher = (() => { } } + const tagsInput = document.getElementById('tags-input'); + const input = document.getElementById('custom_source'); + + const tags = []; + + const addTag = (url) => { + if (tags.includes(url)) return; + tags.push(url); + + const tagElement = document.createElement('span'); + tagElement.className = 'tag'; + tagElement.textContent = url; + + const removeButton = document.createElement('span'); + removeButton.className = 'remove-tag'; + removeButton.textContent = 'x'; + removeButton.onclick = function () { + tagsInput.removeChild(tagElement); + tags.splice(tags.indexOf(url), 1); + }; + + tagElement.appendChild(removeButton); + tagsInput.insertBefore(tagElement, input); + } + document.addEventListener('DOMContentLoaded', init) return { startResearch, copyToClipboard, + changeSource, + addTag, } })() diff --git a/frontend/styles.css b/frontend/styles.css index 24af6e675..f532020d3 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -1,7 +1,13 @@ @keyframes gradientBG { - 0% {background-position: 0% 50%;} - 50% {background-position: 100% 50%;} - 100% {background-position: 0% 50%;} + 0% { + background-position: 0 50%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0 50%; + } } html { @@ -35,27 +41,25 @@ body { font-size: 1.5rem; font-weight: 400; max-width: 500px; - margin: auto; - margin-bottom: 2rem; + margin: auto auto 2rem auto; } .container { - margin: auto; padding: 20px; background-color: rgba(255, 255, 255, 0.1); border-radius: 12px; - box-shadow: 0px 10px 25px rgba(0, 0, 0, 0.1); + box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1); transition: all .3s ease-in-out; - margin-bottom: 180px; + margin: auto auto 180px auto; } .container:hover { transform: scale(1.01); - box-shadow: 0px 15px 30px rgba(0, 0, 0, 0.2); + box-shadow: 0 15px 30px rgba(0, 0, 0, 0.2); } input, select, #output, #reportContainer { - background-color: rgba(255,255,255,0.1); + background-color: rgba(255, 255, 255, 0.1); border: none; color: #fff; transition: all .3s ease-in-out; @@ -64,7 +68,7 @@ input, select, #output, #reportContainer { input:hover, input:focus, select:hover, select:focus { background-color: #dfe4ea; border: 1px solid rgba(255, 255, 255, 0.5); - box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); transition: all 0.3s ease-in-out; } @@ -83,7 +87,7 @@ input:hover, input:focus, select:hover, select:focus { .btn:hover { opacity: 0.8; transform: scale(1.1); - box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.3); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3); } .agent_question { @@ -118,7 +122,7 @@ footer { #output { height: 300px; - font-family: 'Times New Roman', Times, , "Courier New", serif; + font-family: 'Times New Roman', Times, "Courier New", serif; overflow: auto; padding: 10px; margin-bottom: 10px; @@ -127,10 +131,40 @@ footer { } #reportContainer { - background-color: rgba(255,255,255,0.1); + background-color: rgba(255, 255, 255, 0.1); border: none; color: #fff; transition: all .3s ease-in-out; padding: 25px; border-radius: 12px; } + +.tags-input { + display: flex; + flex-wrap: wrap; + gap: 5px; + border: 1px solid #ccc; + padding: 5px; + border-radius: 5px; +} + +.tag { + background-color: #007bff; + color: white; + padding: 5px 10px; + border-radius: 3px; + display: flex; + align-items: center; +} + +.tag .remove-tag { + margin-left: 10px; + cursor: pointer; + font-weight: bold; +} + +.tag-input { + border: none; + outline: none; + flex-grow: 1; +} \ No newline at end of file diff --git a/gpt_researcher/master/agent.py b/gpt_researcher/master/agent.py index 88c160d1e..2808de27e 100644 --- a/gpt_researcher/master/agent.py +++ b/gpt_researcher/master/agent.py @@ -94,7 +94,8 @@ async def conduct_research(self): """ # Reset visited_urls and source_urls at the start of each research task self.visited_urls.clear() - self.source_urls = [] + if self.report_source != ReportSource.Sources.value: + self.source_urls = [] if self.verbose: await stream_output( diff --git a/gpt_researcher/utils/enum.py b/gpt_researcher/utils/enum.py index 5afd9b039..5d6c49cb7 100644 --- a/gpt_researcher/utils/enum.py +++ b/gpt_researcher/utils/enum.py @@ -14,6 +14,7 @@ class ReportSource(Enum): Web = "web" Local = "local" LangChainDocuments = "langchain_documents" + Sources = "sources" class Tone(Enum): diff --git a/multi_agents/frontend/components/Search.tsx b/multi_agents/frontend/components/Search.tsx index 1b19b5cda..411f369bc 100644 --- a/multi_agents/frontend/components/Search.tsx +++ b/multi_agents/frontend/components/Search.tsx @@ -46,7 +46,7 @@ const Search = () => { setReportType(reportType); setReportSource(reportSource); // Send data to WebSocket server if needed - let data = "start " + JSON.stringify({ task: task.value, report_type: report_type.value, report_source: report_source.value }); + let data = "start " + JSON.stringify({ task: task.value, report_type: reportType.value, report_source: reportSource.value }); socket.send(data); }; diff --git a/multi_agents/frontend/components/Settings/FileUpload.js b/multi_agents/frontend/components/Settings/FileUpload.js index 9d63d55d7..e7c34a204 100644 --- a/multi_agents/frontend/components/Settings/FileUpload.js +++ b/multi_agents/frontend/components/Settings/FileUpload.js @@ -50,20 +50,30 @@ const FileUpload = () => { const { getRootProps, getInputProps } = useDropzone({ onDrop }); return ( -
+
-

Drag 'n' drop some files here, or click to select files

+

Drag 'n' drop some files here, or click to select files

-

Uploaded Files

- + {files.length > 0 && ( + <> +

Uploaded Files

+ + + )}
); };