feat : slight fix attempt for frontend

This commit is contained in:
martin legrand 2025-04-21 15:06:21 +02:00
parent 4de527aa42
commit 1b17b95e8c
5 changed files with 29 additions and 17 deletions

12
api.py
View File

@ -12,6 +12,7 @@ from fastapi.responses import JSONResponse
from fastapi.responses import FileResponse from fastapi.responses import FileResponse
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
import uuid
from sources.llm_provider import Provider from sources.llm_provider import Provider
from sources.interaction import Interaction from sources.interaction import Interaction
@ -21,6 +22,7 @@ from sources.utility import pretty_print
from sources.logger import Logger from sources.logger import Logger
from sources.schemas import QueryRequest, QueryResponse from sources.schemas import QueryRequest, QueryResponse
from celery import Celery from celery import Celery
api = FastAPI(title="AgenticSeek API", version="0.1.0") api = FastAPI(title="AgenticSeek API", version="0.1.0")
@ -131,7 +133,8 @@ async def get_latest_answer():
global query_resp_history global query_resp_history
if interaction.current_agent is None: if interaction.current_agent is None:
return JSONResponse(status_code=404, content={"error": "No agent available"}) 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 = { query_resp = {
"done": "false", "done": "false",
"answer": interaction.current_agent.last_answer, "answer": interaction.current_agent.last_answer,
@ -139,8 +142,9 @@ async def get_latest_answer():
"success": interaction.current_agent.success, "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 {}, "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", "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) query_resp_history.append(query_resp)
return JSONResponse(status_code=200, content=query_resp) return JSONResponse(status_code=200, content=query_resp)
if query_resp_history: if query_resp_history:
@ -176,7 +180,7 @@ async def process_query(request: QueryRequest):
success="false", success="false",
blocks={}, blocks={},
status="Ready", status="Ready",
timestamp=str(time.time()) uid=str(uuid.uuid4())
) )
if is_generating: if is_generating:
logger.warning("Another query is being processed, please wait.") logger.warning("Another query is being processed, please wait.")
@ -215,7 +219,7 @@ async def process_query(request: QueryRequest):
"success": query_resp.success, "success": query_resp.success,
"blocks": query_resp.blocks, "blocks": query_resp.blocks,
"status": query_resp.status, "status": query_resp.status,
"timestamp": query_resp.timestamp "uid": query_resp.uid
} }
query_resp_history.append(query_resp_dict) query_resp_history.append(query_resp_dict)

View File

@ -18,7 +18,7 @@ function App() {
checkHealth(); checkHealth();
fetchLatestAnswer(); fetchLatestAnswer();
fetchScreenshot(); fetchScreenshot();
}, 1500); }, 3000);
return () => clearInterval(intervalId); return () => clearInterval(intervalId);
}, [messages]); }, [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 = () => { const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
@ -75,12 +81,10 @@ function App() {
if (!data.answer || data.answer.trim() === '') { if (!data.answer || data.answer.trim() === '') {
return; return;
} }
const normalizedNewAnswer = normalizeAnswer(data.answer);
const answerExists = messages.some( const answerExists = messages.some(
(msg) => (msg) => normalizeAnswer(msg.content) === normalizedNewAnswer
msg.timestamp === data.timestamp &&
normalizeAnswer(msg.content) === normalizeAnswer(data.answer)
); );
console.log('Fetched latest answer:', data.answer);
if (!answerExists) { if (!answerExists) {
setMessages((prev) => [ setMessages((prev) => [
...prev, ...prev,
@ -89,17 +93,19 @@ function App() {
content: data.answer, content: data.answer,
agentName: data.agent_name, agentName: data.agent_name,
status: data.status, status: data.status,
timestamp: data.timestamp, uid: data.uid,
}, },
]); ]);
setStatus(data.status); setStatus(data.status);
scrollToBottom(); scrollToBottom();
} else {
console.log('Duplicate answer detected, skipping:', data.answer);
} }
} catch (error) { } catch (error) {
console.error('Error fetching latest answer:', error); console.error('Error fetching latest answer:', error);
} }
}; };
const handleSubmit = async (e) => { const handleSubmit = async (e) => {
e.preventDefault(); e.preventDefault();

View File

@ -115,7 +115,7 @@ class Agent():
def extract_reasoning_text(self, text: str) -> None: 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 = "<think>" start_tag = "<think>"
end_tag = "</think>" end_tag = "</think>"

View File

@ -244,7 +244,7 @@ class Browser:
def is_link_valid(self, url:str) -> bool: def is_link_valid(self, url:str) -> bool:
"""Check if a URL is a valid link (page, not related to icon or metadata).""" """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}") self.logger.warning(f"URL too long: {url}")
return False return False
parsed_url = urlparse(url) parsed_url = urlparse(url)

View File

@ -23,10 +23,10 @@ class QueryResponse(BaseModel):
success: str success: str
blocks: dict blocks: dict
status: str status: str
timestamp: str uid: str
def __str__(self): 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): def jsonify(self):
return { return {
@ -34,7 +34,9 @@ class QueryResponse(BaseModel):
"answer": self.answer, "answer": self.answer,
"agent_name": self.agent_name, "agent_name": self.agent_name,
"success": self.success, "success": self.success,
"blocks": self.blocks "blocks": self.blocks,
"status": self.status,
"uid": self.uid
} }
class executorResult: class executorResult: