diff --git a/api.py b/api.py index 5dcb1ad..862758f 100755 --- a/api.py +++ b/api.py @@ -12,6 +12,7 @@ from fastapi.responses import JSONResponse from fastapi.responses import FileResponse from fastapi.middleware.cors import CORSMiddleware from fastapi.staticfiles import StaticFiles +import uuid from sources.llm_provider import Provider from sources.interaction import Interaction @@ -21,6 +22,7 @@ from sources.utility import pretty_print from sources.logger import Logger from sources.schemas import QueryRequest, QueryResponse + from celery import Celery api = FastAPI(title="AgenticSeek API", version="0.1.0") @@ -131,7 +133,8 @@ async def get_latest_answer(): global query_resp_history if interaction.current_agent is None: return JSONResponse(status_code=404, content={"error": "No agent available"}) - if interaction.current_agent.last_answer not in [q["answer"] for q in query_resp_history]: + uid = str(uuid.uuid4()) + if not any(q["answer"] == interaction.current_agent.last_answer for q in query_resp_history): query_resp = { "done": "false", "answer": interaction.current_agent.last_answer, @@ -139,8 +142,9 @@ async def get_latest_answer(): "success": interaction.current_agent.success, "blocks": {f'{i}': block.jsonify() for i, block in enumerate(interaction.current_agent.get_blocks_result())} if interaction.current_agent else {}, "status": interaction.current_agent.get_status_message if interaction.current_agent else "No status available", - "timestamp": str(time.time()) + "uid": uid } + interaction.current_agent.last_answer = "" query_resp_history.append(query_resp) return JSONResponse(status_code=200, content=query_resp) if query_resp_history: @@ -176,7 +180,7 @@ async def process_query(request: QueryRequest): success="false", blocks={}, status="Ready", - timestamp=str(time.time()) + uid=str(uuid.uuid4()) ) if is_generating: logger.warning("Another query is being processed, please wait.") @@ -215,7 +219,7 @@ async def process_query(request: QueryRequest): "success": query_resp.success, "blocks": query_resp.blocks, "status": query_resp.status, - "timestamp": query_resp.timestamp + "uid": query_resp.uid } query_resp_history.append(query_resp_dict) diff --git a/frontend/agentic-seek-front/src/App.js b/frontend/agentic-seek-front/src/App.js index d8a1114..ffcb68a 100644 --- a/frontend/agentic-seek-front/src/App.js +++ b/frontend/agentic-seek-front/src/App.js @@ -18,7 +18,7 @@ function App() { checkHealth(); fetchLatestAnswer(); fetchScreenshot(); - }, 1500); + }, 3000); return () => clearInterval(intervalId); }, [messages]); @@ -61,7 +61,13 @@ function App() { } }; - const normalizeAnswer = (answer) => answer.trim().toLowerCase(); + const normalizeAnswer = (answer) => { + return answer + .trim() + .toLowerCase() + .replace(/\s+/g, ' ') + .replace(/[.,!?]/g, '') + }; const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); @@ -75,12 +81,10 @@ function App() { if (!data.answer || data.answer.trim() === '') { return; } + const normalizedNewAnswer = normalizeAnswer(data.answer); const answerExists = messages.some( - (msg) => - msg.timestamp === data.timestamp && - normalizeAnswer(msg.content) === normalizeAnswer(data.answer) + (msg) => normalizeAnswer(msg.content) === normalizedNewAnswer ); - console.log('Fetched latest answer:', data.answer); if (!answerExists) { setMessages((prev) => [ ...prev, @@ -89,17 +93,19 @@ function App() { content: data.answer, agentName: data.agent_name, status: data.status, - timestamp: data.timestamp, + uid: data.uid, }, ]); setStatus(data.status); scrollToBottom(); + } else { + console.log('Duplicate answer detected, skipping:', data.answer); } } catch (error) { console.error('Error fetching latest answer:', error); } }; - + const handleSubmit = async (e) => { e.preventDefault(); diff --git a/sources/agents/agent.py b/sources/agents/agent.py index 323c14b..387189e 100644 --- a/sources/agents/agent.py +++ b/sources/agents/agent.py @@ -115,7 +115,7 @@ class Agent(): def extract_reasoning_text(self, text: str) -> None: """ - Extract the reasoning block of a easoning model like deepseek. + Extract the reasoning block of a reasoning model like deepseek. """ start_tag = "" end_tag = "" diff --git a/sources/browser.py b/sources/browser.py index 69e9022..26429b7 100644 --- a/sources/browser.py +++ b/sources/browser.py @@ -244,7 +244,7 @@ class Browser: def is_link_valid(self, url:str) -> bool: """Check if a URL is a valid link (page, not related to icon or metadata).""" - if len(url) > 64: + if len(url) > 72: self.logger.warning(f"URL too long: {url}") return False parsed_url = urlparse(url) diff --git a/sources/schemas.py b/sources/schemas.py index 04fb900..ad72830 100644 --- a/sources/schemas.py +++ b/sources/schemas.py @@ -23,10 +23,10 @@ class QueryResponse(BaseModel): success: str blocks: dict status: str - timestamp: str + uid: str def __str__(self): - return f"Done: {self.done}, Answer: {self.answer}, Agent Name: {self.agent_name}, Success: {self.success}, Blocks: {self.blocks}" + return f"Done: {self.done}, Answer: {self.answer}, Agent Name: {self.agent_name}, Success: {self.success}, Blocks: {self.blocks}, Status: {self.status}, UID: {self.uid}" def jsonify(self): return { @@ -34,7 +34,9 @@ class QueryResponse(BaseModel): "answer": self.answer, "agent_name": self.agent_name, "success": self.success, - "blocks": self.blocks + "blocks": self.blocks, + "status": self.status, + "uid": self.uid } class executorResult: