mirror of
https://github.com/tcsenpai/agenticSeek.git
synced 2025-06-05 02:25:27 +00:00
Merge pull request #126 from Fosowl/dev
Update readme and slight frontend fix attempt
This commit is contained in:
commit
50142b48f8
@ -15,6 +15,7 @@ English | [中文](./README_CHS.md) | [繁體中文](./README_CHT.md) | [Franç
|
||||
> 🛠️ **Work in Progress** – Looking for contributors!
|
||||
|
||||
|
||||
|
||||
https://github.com/user-attachments/assets/4bd5faf6-459f-4f94-bd1d-238c4b331469
|
||||
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
**Manus AI 的本地替代品**,它是一个具有语音功能的大语言模型秘书,可以 Coding、访问你的电脑文件、浏览网页,并自动修正错误与反省,最重要的是不会向云端传送任何资料。采用 DeepSeek R1 等推理模型构建,完全在本地硬体上运行,进而保证资料的隐私。
|
||||
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/4Ub2D6Fj) [](https://x.com/Martin993886460)
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/XSTKZ8nP) [](https://x.com/Martin993886460)
|
||||
|
||||
> 🛠️ **目前还在开发阶段** – 欢迎任何贡献者加入我们!
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
**Manus AI 的本地替代品**,它是一個具有語音功能的大語言模型秘書,可以 Coding、訪問你的電腦文件、瀏覽網頁,並自動修正錯誤與反省,最重要的是不會向雲端傳送任何資料。採用 DeepSeek R1 等推理模型構建,完全在本地硬體上運行,進而保證資料的隱私。
|
||||
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/4Ub2D6Fj) [](https://x.com/Martin993886460)
|
||||
[](https://fosowl.github.io/agenticSeek.html)  [](https://discord.gg/XSTKZ8nP) [](https://x.com/Martin993886460)
|
||||
|
||||
> 🛠️ **目前還在開發階段** – 歡迎任何貢獻者加入我們!
|
||||
|
||||
|
12
api.py
12
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)
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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 = "<think>"
|
||||
end_tag = "</think>"
|
||||
|
@ -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)
|
||||
|
@ -22,7 +22,7 @@ class Provider:
|
||||
self.provider_name = provider_name.lower()
|
||||
self.model = model
|
||||
self.is_local = is_local
|
||||
self.server_ip = self.check_address_format(server_address)
|
||||
self.server_ip = server_address
|
||||
self.available_providers = {
|
||||
"ollama": self.ollama_fn,
|
||||
"server": self.server_fn,
|
||||
@ -44,7 +44,6 @@ class Provider:
|
||||
self.api_key = self.get_api_key(self.provider_name)
|
||||
elif self.provider_name != "ollama":
|
||||
pretty_print(f"Provider: {provider_name} initialized at {self.server_ip}", color="success")
|
||||
self.check_address_format(self.server_ip)
|
||||
if not self.is_ip_online(self.server_ip.split(':')[0]):
|
||||
raise Exception(f"Server at {self.server_ip} is offline.")
|
||||
|
||||
@ -57,21 +56,6 @@ class Provider:
|
||||
exit(1)
|
||||
return api_key
|
||||
|
||||
def check_address_format(self, address):
|
||||
"""
|
||||
Validate if the address is valid IP.
|
||||
"""
|
||||
try:
|
||||
address = address.replace('http://', '')
|
||||
ip, port = address.rsplit(":", 1)
|
||||
if all(c.lower() in ".:abcdef0123456789" for c in ip):
|
||||
ipaddress.ip_address(ip)
|
||||
if not port.isdigit() or not (0 <= int(port) <= 65535):
|
||||
raise ValueError("Port must be a number between 0 and 65535.")
|
||||
except ValueError as e:
|
||||
raise Exception(f"Invalid address format: {e}. Is port specified?")
|
||||
return address
|
||||
|
||||
def respond(self, history, verbose = True):
|
||||
"""
|
||||
Use the choosen provider to generate text.
|
||||
|
@ -178,6 +178,7 @@ class AgentRouter:
|
||||
("Find a public API for movie data and build a web app to display movie ratings", "HIGH"),
|
||||
("Create a Node.js server that queries a public API for traffic data and displays it", "HIGH"),
|
||||
("can you find api and build a python web app with it ?", "HIGH"),
|
||||
("do a deep search of current AI player for 2025 and make me a report in a file", "HIGH"),
|
||||
("Find a public API for recipe data and build a web app to display recipes", "HIGH"),
|
||||
("Search the web for recent space mission updates and build a Flask app", "HIGH"),
|
||||
("Create a Python script to scrape a website and save data to a database", "HIGH"),
|
||||
|
@ -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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user