Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ token.pickle
chatsDb.json
userProfileDb.json
tasks.json
context.json
memory_operations.json
ruff_cache
.db
19 changes: 19 additions & 0 deletions src/interface/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,25 @@ ws.onmessage = (event) => {
title: "Task Error!",
body: `Task "${description}" (ID: ${task_id}) encountered an error.\nError: ${error}`
}).show()
} else if (messageData.type === "memory_operation_completed") {
const { operation_id, status, fact } = messageData
new Notification({
title: "Memory Operation Completed!",
body: `Memory operation (ID: ${operation_id}) was successful.\nFact: ${fact.substring(0, 100)}...` // Limit fact preview
}).show()
} else if (messageData.type === "memory_operation_error") {
const { operation_id, error, fact } = messageData
new Notification({
title: "Memory Operation Error!",
body: `Memory operation (ID: ${operation_id}) encountered an error.\nError: ${error}\nFact: ${fact.substring(0, 100)}...` // Limit fact preview
}).show()
} else if (messageData.type === "new_message") {
const { message } = messageData
console.log("New message received:", message)
new Notification({
title: "New Message!",
body: message.substring(0, 100) + "..." // Show a preview of the message
}).show()
}
}

Expand Down
Binary file modified src/memory.db
Binary file not shown.
68 changes: 41 additions & 27 deletions src/model/app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,12 @@
import pickle
import multiprocessing
import requests
from datetime import datetime, timezone, timedelta
from tzlocal import get_localzone
from datetime import datetime, timezone
from fastapi import FastAPI, HTTPException
from fastapi.responses import JSONResponse, StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Optional, Any, Dict, List, AsyncGenerator
from typing import Optional, Any, Dict, List
from neo4j import GraphDatabase
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from google_auth_oauthlib.flow import InstalledAppFlow
Expand All @@ -37,7 +36,6 @@
from model.memory.constants import *
from model.memory.formats import *
from model.memory.backend import MemoryBackend
from model.memory.dual_memory import MemoryManager

from model.utils.helpers import *

Expand All @@ -57,6 +55,9 @@
from model.chat.prompts import *
from model.chat.functions import *

from model.context.gmail import GmailContextEngine
from model.context.internet import InternetSearchContextEngine
from model.context.gcalendar import GCalendarContextEngine

# Load environment variables from .env file
load_dotenv("model/.env")
Expand All @@ -76,6 +77,28 @@
auth=(os.environ["NEO4J_USERNAME"], os.environ["NEO4J_PASSWORD"])
)

class WebSocketManager:
def __init__(self):
self.active_connections: List[WebSocket] = []

async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)

def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)

async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_text(message)

async def broadcast(self, message: str):
for connection in self.active_connections:
try:
await connection.send_text(message)
except Exception as e:
print(f"Error broadcasting message to connection: {e}")
self.disconnect(connection) # Remove broken connection

manager = WebSocketManager()

# Initialize runnables from agents
Expand Down Expand Up @@ -253,28 +276,6 @@ async def get_chat_history_messages() -> List[Dict[str, Any]]:
else:
return []

class WebSocketManager:
def __init__(self):
self.active_connections: List[WebSocket] = []

async def connect(self, websocket: WebSocket):
await websocket.accept()
self.active_connections.append(websocket)

def disconnect(self, websocket: WebSocket):
self.active_connections.remove(websocket)

async def send_personal_message(self, message: str, websocket: WebSocket):
await websocket.send_text(message)

async def broadcast(self, message: str):
for connection in self.active_connections:
try:
await connection.send_text(message)
except Exception as e:
print(f"Error broadcasting message to connection: {e}")
self.disconnect(connection) # Remove broken connection

async def cleanup_tasks_periodically():
"""Periodically clean up old completed tasks."""
while True:
Expand Down Expand Up @@ -333,7 +334,6 @@ async def process_memory_operations():
while True:
operation = await memory_backend.memory_queue.get_next_operation()

print(f"Processing memory operation: {operation}")
if operation:
try:
user_id = operation["user_id"]
Expand Down Expand Up @@ -518,6 +518,20 @@ async def startup_event():
asyncio.create_task(process_queue())
asyncio.create_task(process_memory_operations())
asyncio.create_task(cleanup_tasks_periodically())

user_id = "user1" # Replace with dynamic user ID retrieval if needed
enabled_data_sources = ["gmail", "internet_search", "gcalendar"] # Add gcalendar here

for source in enabled_data_sources:
if source == "gmail":
engine = GmailContextEngine(user_id, task_queue, memory_backend, manager, db_lock)
elif source == "internet_search":
engine = InternetSearchContextEngine(user_id, task_queue, memory_backend, manager, db_lock)
elif source == "gcalendar":
engine = GCalendarContextEngine(user_id, task_queue, memory_backend, manager, db_lock)
else:
continue # Skip unrecognized sources
asyncio.create_task(engine.start())

@app.on_event("shutdown")
async def shutdown_event():
Expand Down
27 changes: 27 additions & 0 deletions src/model/app/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,3 +361,30 @@ def write_to_log(message: str):
f"Error writing to log file: {error}"
) # Print error message if writing to log file fails

CHAT_DB = "chatsDb.json"
initial_db = {
"chats": [],
"active_chat_id": None,
"next_chat_id": 1
}

async def load_db():
"""Load the database from chatsDb.json, initializing if it doesn't exist or is invalid."""
try:
with open(CHAT_DB, 'r', encoding='utf-8') as f:
data = json.load(f)
if "chats" not in data:
data["chats"] = []
if "active_chat_id" not in data:
data["active_chat_id"] = None
if "next_chat_id" not in data:
data["next_chat_id"] = 1
return data
except (FileNotFoundError, json.JSONDecodeError):
print("DB NOT FOUND! Initializing with default structure.")
return initial_db

async def save_db(data):
"""Save the data to chatsDb.json."""
with open(CHAT_DB, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=4)
63 changes: 49 additions & 14 deletions src/model/common/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,49 +344,84 @@
"""

internet_summary_system_prompt_template = """
You are tasked with summarizing a list of search results provided as plain strings into a concise, coherent, and unstructured paragraph.
You are tasked with summarizing a list of search results provided as a list of dictionaries into a concise, coherent, and unstructured paragraph. Each dictionary contains "title", "url", and "description". Your summary should integrate relevant URLs to enhance its utility and provide direct access to sources.

### Instructions:
1. Combine all the results into a single paragraph that captures the key points across all the items.
1. Combine information from the "title" and "description" of each search result into a single paragraph that captures the key points across all items.
2. Avoid repeating information but ensure no important detail is omitted.
3. Maintain a neutral and professional tone.
4. Do not list the results as individual items; instead, weave them seamlessly into a cohesive narrative.
5. Use appropriate transitions to link related points.
6. Avoid directly quoting unless necessary for clarity or emphasis.
7. **Integrate relevant URLs within the summary paragraph to provide context and direct access to sources. Focus on including URLs for primary sources or when a direct link significantly benefits the reader. Be selective and strategic in URL inclusion to maximize the summary's value.** You are not required to include every URL.
8. You can mention the source name (from the title if appropriate) and then include the URL in parentheses, or find other natural ways to integrate URLs.

### Input Format:
- A simple list of strings, where each string represents a search result or description.
- A list of dictionaries, where each dictionary represents a search result and contains the keys: "title", "url", and "description".

### Output Format:
- A single unstructured paragraph that summarizes the key points from the input.
- A single unstructured paragraph that summarizes the key points from the input, incorporating relevant URLs.

### Examples:

#### Example 1:
Input:
[
"Climate change is causing rising temperatures worldwide.",
"Polar regions are experiencing faster ice melting due to global warming.",
"Melting ice is contributing to rising sea levels, threatening coastal areas."
{"title": "Climate change is causing rising temperatures worldwide.", "url": "url1", "description": "Global warming is leading to increased temperatures across the planet."},
{"title": "Polar regions are experiencing faster ice melting.", "url": "url2", "description": "Due to global warming, ice is melting rapidly in polar areas."},
{"title": "Melting ice causes rising sea levels.", "url": "url3", "description": "The melting of polar ice contributes to the increase in sea levels, posing risks to coastal regions."}
]

Output:
Climate change is leading to rising global temperatures, significantly impacting polar regions, where ice is melting at an accelerated rate. This phenomenon is contributing to rising sea levels, which pose a substantial threat to coastal communities.
Climate change, also known as global warming, is causing rising temperatures worldwide, especially impacting polar regions where ice is melting at an accelerated rate. This melting ice is a significant contributor to rising sea levels, which threatens coastal areas. Sources indicate these effects are globally observed (url1), particularly pronounced in polar regions (url2), and lead to sea level rise (url3).

#### Example 2:
Input:
[
"A balanced diet includes fruits, vegetables, proteins, and whole grains.",
"Staying hydrated is crucial for maintaining overall health.",
"Regular exercise improves cardiovascular health and mental well-being."
{"title": "Balanced diet includes fruits, vegetables.", "url": "url4", "description": "A healthy diet should consist of fruits and vegetables."},
{"title": "Hydration is crucial for health.", "url": "url5", "description": "Staying hydrated is very important for maintaining good health."},
{"title": "Exercise improves cardiovascular health.", "url": "url6", "description": "Regular physical activity benefits the heart and blood vessels."}
]

Output:
A healthy lifestyle encompasses consuming a balanced diet rich in fruits, vegetables, proteins, and whole grains, while staying hydrated is essential for overall well-being. Incorporating regular exercise further enhances cardiovascular health and supports mental wellness.
A healthy lifestyle includes a balanced diet with fruits and vegetables (url4), and staying hydrated is crucial for overall health (url5). Furthermore, regular exercise is beneficial for improving cardiovascular health (url6).

#### Example 3:
Input:
[
{
"title": "Breaking News, Latest News and Videos | CNN",
"url": "https://www.cnn.com/",
"description": "View the latest news and breaking news today for U.S., world, weather, entertainment, politics and health at CNN.com."
},
{
"title": "Fox News - Breaking News Updates | Latest News Headlines | Photos & News Videos",
"url": "https://www.foxnews.com/",
"description": "Breaking News, Latest News and Current News from FOXNews.com. Breaking news and video. Latest Current News: U.S., World, Entertainment, Health, Business, Technology, Politics, Sports"
},
{
"title": "NBC News - Breaking News & Top Stories - Latest World, US & Local News | NBC News",
"url": "https://www.nbcnews.com/",
"description": "Go to NBCNews.com for breaking news, videos, and the latest top stories in world news, business, politics, health and pop culture."
},
{
"title": "Associated Press News: Breaking News, Latest Headlines and Videos | AP News",
"url": "https://apnews.com/",
"description": "Read the latest headlines, breaking news, and videos at APNews.com, the definitive source for independent journalism from every corner of the globe."
},
{
"title": "Google News",
"url": "https://news.google.com/",
"description": "Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for."
}
]

Output:
Major news outlets such as CNN (https://www.cnn.com/), Fox News (https://www.foxnews.com/), NBC News (https://www.nbcnews.com/), and Associated Press (AP) (https://apnews.com/) offer breaking and current news coverage spanning U.S. and world events, alongside topics like weather, entertainment, politics, health, business, technology, sports, and pop culture, typically through articles and videos. Google News (https://news.google.com/) also provides a comprehensive news aggregation service, sourcing information from across the globe.
"""

internet_summary_user_prompt_template = """Summarize the provided list of search results into a single, coherent paragraph.
internet_summary_user_prompt_template = """Summarize the provided list of search results into a single, coherent paragraph, including relevant source URLs.


{query}
"""
"""
Loading
Loading