Spaces:
Runtime error
Runtime error
Upload 25 files
Browse files- .github/workflows/deploy.yml +16 -0
- README.md +32 -34
- agent.py +12 -23
- api.py +16 -0
- auth.py +7 -12
- memory.py +38 -0
- session.py +26 -0
.github/workflows/deploy.yml
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
name: Deploy Autonomous AI
|
| 3 |
+
|
| 4 |
+
on:
|
| 5 |
+
push:
|
| 6 |
+
branches: [ main ]
|
| 7 |
+
|
| 8 |
+
jobs:
|
| 9 |
+
build-and-deploy:
|
| 10 |
+
runs-on: ubuntu-latest
|
| 11 |
+
steps:
|
| 12 |
+
- uses: actions/checkout@v3
|
| 13 |
+
- name: Build Docker image
|
| 14 |
+
run: docker build -t autonomous-ai .
|
| 15 |
+
- name: Run container
|
| 16 |
+
run: docker run -d -p 8000:8000 autonomous-ai
|
README.md
CHANGED
|
@@ -1,34 +1,32 @@
|
|
| 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 |
-
2. Set type to `Gradio`
|
| 34 |
-
3. Enjoy your AI developer assistant
|
|
|
|
| 1 |
+
|
| 2 |
+
# Autonomous AI — Self-Improving Agent
|
| 3 |
+
|
| 4 |
+
This is an autonomous AI system capable of learning, improving, and handling tasks via API, Webhooks, and a Client Portal.
|
| 5 |
+
|
| 6 |
+
## 🚀 Features
|
| 7 |
+
- Self-upgrading agent loop
|
| 8 |
+
- Multi-agent collaboration
|
| 9 |
+
- Feedback storage + analytics dashboard
|
| 10 |
+
- Webhook + portal UI
|
| 11 |
+
- Scheduler & voice interface
|
| 12 |
+
|
| 13 |
+
## 🐳 Deploy with Docker
|
| 14 |
+
|
| 15 |
+
```bash
|
| 16 |
+
docker build -t autonomous-ai .
|
| 17 |
+
docker run -p 8000:8000 autonomous-ai
|
| 18 |
+
```
|
| 19 |
+
|
| 20 |
+
Visit: http://localhost:8000/portal
|
| 21 |
+
|
| 22 |
+
## 🌐 Manual Start (No Docker)
|
| 23 |
+
```bash
|
| 24 |
+
pip install -r requirements.txt
|
| 25 |
+
python -c "from storage import init_db; init_db()"
|
| 26 |
+
uvicorn api:app --reload
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
## 🛠 Endpoints
|
| 30 |
+
- `/portal` - Task submission UI
|
| 31 |
+
- `/dashboard` - Feedback/goal display
|
| 32 |
+
- `/webhook` - POST task externally
|
|
|
|
|
|
agent.py
CHANGED
|
@@ -1,24 +1,13 @@
|
|
| 1 |
|
| 2 |
-
import
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
result = run_code(code)
|
| 15 |
-
|
| 16 |
-
# Save memory and logs
|
| 17 |
-
write_memory(f"{datetime.now()}: Completed task '{task}'")
|
| 18 |
-
save_log(task, plan, code, result)
|
| 19 |
-
|
| 20 |
-
return f"✅ Task Complete:\nPlan: {plan}\n\nCode:\n{code}\n\nResult:\n{result}"
|
| 21 |
-
except Exception as e:
|
| 22 |
-
error = traceback.format_exc()
|
| 23 |
-
save_log(task, "FAILED", "None", error)
|
| 24 |
-
return f"❌ Task Failed:\n{error}"
|
|
|
|
| 1 |
|
| 2 |
+
from memory import MemoryVectorStore
|
| 3 |
+
|
| 4 |
+
memory = MemoryVectorStore()
|
| 5 |
+
|
| 6 |
+
def run_agent(goal):
|
| 7 |
+
memory.add(goal)
|
| 8 |
+
ideas = memory.search(goal)
|
| 9 |
+
# Assume goal is passed into LLM with memory summary
|
| 10 |
+
summary = " ".join(ideas)
|
| 11 |
+
result = f"[Task]: {goal}\n[Memory]: {summary}\n[Response]: working on it..."
|
| 12 |
+
memory.add(result)
|
| 13 |
+
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api.py
CHANGED
|
@@ -53,3 +53,19 @@ async def submit_task(goal: str = Form(...)):
|
|
| 53 |
async def dashboard():
|
| 54 |
with open("dashboard.html") as f:
|
| 55 |
return f.read()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 53 |
async def dashboard():
|
| 54 |
with open("dashboard.html") as f:
|
| 55 |
return f.read()
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
from fastapi import Header, HTTPException
|
| 59 |
+
from auth import authorize
|
| 60 |
+
from session import log_interaction, create_session
|
| 61 |
+
|
| 62 |
+
@app.post("/session_task")
|
| 63 |
+
def session_task(goal: str, x_api_key: str = Header(...), session_id: str = ""):
|
| 64 |
+
user = authorize(x_api_key)
|
| 65 |
+
if not user:
|
| 66 |
+
raise HTTPException(status_code=401, detail="Invalid API key")
|
| 67 |
+
if not session_id:
|
| 68 |
+
session_id = create_session(user)
|
| 69 |
+
output = run_agent(goal)
|
| 70 |
+
log_interaction(session_id, goal, output)
|
| 71 |
+
return {"session_id": session_id, "output": output}
|
auth.py
CHANGED
|
@@ -1,14 +1,9 @@
|
|
| 1 |
|
| 2 |
-
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
class APIKeyMiddleware(BaseHTTPMiddleware):
|
| 8 |
-
async def dispatch(self, request: Request, call_next):
|
| 9 |
-
if request.url.path.startswith("/"):
|
| 10 |
-
api_key = request.headers.get("x-api-key")
|
| 11 |
-
if api_key != API_KEY:
|
| 12 |
-
raise HTTPException(status_code=401, detail="Invalid API Key")
|
| 13 |
-
response = await call_next(request)
|
| 14 |
-
return response
|
|
|
|
| 1 |
|
| 2 |
+
# Very simple API key system
|
| 3 |
+
AUTHORIZED_KEYS = {
|
| 4 |
+
"admin-key": "admin",
|
| 5 |
+
"user-key": "user"
|
| 6 |
+
}
|
| 7 |
|
| 8 |
+
def authorize(key: str):
|
| 9 |
+
return AUTHORIZED_KEYS.get(key)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memory.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import os
|
| 3 |
+
import faiss
|
| 4 |
+
import pickle
|
| 5 |
+
from sentence_transformers import SentenceTransformer
|
| 6 |
+
from logger import logger
|
| 7 |
+
|
| 8 |
+
class MemoryVectorStore:
|
| 9 |
+
def __init__(self, path="memory_index"):
|
| 10 |
+
self.path = path
|
| 11 |
+
self.model = SentenceTransformer("all-MiniLM-L6-v2")
|
| 12 |
+
self.dim = 384
|
| 13 |
+
self.index = faiss.IndexFlatL2(self.dim)
|
| 14 |
+
self.memory = []
|
| 15 |
+
self.load()
|
| 16 |
+
|
| 17 |
+
def load(self):
|
| 18 |
+
if os.path.exists(self.path + ".pkl"):
|
| 19 |
+
with open(self.path + ".pkl", "rb") as f:
|
| 20 |
+
data = pickle.load(f)
|
| 21 |
+
self.memory = data["memory"]
|
| 22 |
+
self.index = data["index"]
|
| 23 |
+
logger.info("✅ Memory index loaded")
|
| 24 |
+
|
| 25 |
+
def save(self):
|
| 26 |
+
with open(self.path + ".pkl", "wb") as f:
|
| 27 |
+
pickle.dump({"memory": self.memory, "index": self.index}, f)
|
| 28 |
+
|
| 29 |
+
def add(self, text):
|
| 30 |
+
vec = self.model.encode([text])
|
| 31 |
+
self.index.add(vec)
|
| 32 |
+
self.memory.append(text)
|
| 33 |
+
self.save()
|
| 34 |
+
|
| 35 |
+
def search(self, query, k=3):
|
| 36 |
+
vec = self.model.encode([query])
|
| 37 |
+
D, I = self.index.search(vec, k)
|
| 38 |
+
return [self.memory[i] for i in I[0] if i < len(self.memory)]
|
session.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
import sqlite3
|
| 3 |
+
from uuid import uuid4
|
| 4 |
+
|
| 5 |
+
def init_session_db():
|
| 6 |
+
conn = sqlite3.connect("sessions.db")
|
| 7 |
+
conn.execute("CREATE TABLE IF NOT EXISTS sessions (id TEXT PRIMARY KEY, user TEXT)")
|
| 8 |
+
conn.execute("CREATE TABLE IF NOT EXISTS messages (session_id TEXT, user_input TEXT, ai_output TEXT)")
|
| 9 |
+
conn.commit()
|
| 10 |
+
conn.close()
|
| 11 |
+
|
| 12 |
+
def create_session(user):
|
| 13 |
+
sid = str(uuid4())
|
| 14 |
+
with sqlite3.connect("sessions.db") as conn:
|
| 15 |
+
conn.execute("INSERT INTO sessions (id, user) VALUES (?, ?)", (sid, user))
|
| 16 |
+
return sid
|
| 17 |
+
|
| 18 |
+
def log_interaction(session_id, user_input, ai_output):
|
| 19 |
+
with sqlite3.connect("sessions.db") as conn:
|
| 20 |
+
conn.execute("INSERT INTO messages (session_id, user_input, ai_output) VALUES (?, ?, ?)",
|
| 21 |
+
(session_id, user_input, ai_output))
|
| 22 |
+
|
| 23 |
+
def get_session_logs(session_id):
|
| 24 |
+
with sqlite3.connect("sessions.db") as conn:
|
| 25 |
+
rows = conn.execute("SELECT user_input, ai_output FROM messages WHERE session_id=?", (session_id,)).fetchall()
|
| 26 |
+
return rows
|