Skip to content

Commit 9ac37df

Browse files
Merge pull request #54 from existence-master/feature/intent
Proactiveness with Gmail, Gcalendar and internet search
2 parents 0951c6a + 9ccd21b commit 9ac37df

File tree

18 files changed

+1028
-46
lines changed

18 files changed

+1028
-46
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ token.pickle
240240
chatsDb.json
241241
userProfileDb.json
242242
tasks.json
243+
context.json
243244
memory_operations.json
244245
ruff_cache
245246
.db

src/interface/main/index.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,25 @@ ws.onmessage = (event) => {
131131
title: "Task Error!",
132132
body: `Task "${description}" (ID: ${task_id}) encountered an error.\nError: ${error}`
133133
}).show()
134+
} else if (messageData.type === "memory_operation_completed") {
135+
const { operation_id, status, fact } = messageData
136+
new Notification({
137+
title: "Memory Operation Completed!",
138+
body: `Memory operation (ID: ${operation_id}) was successful.\nFact: ${fact.substring(0, 100)}...` // Limit fact preview
139+
}).show()
140+
} else if (messageData.type === "memory_operation_error") {
141+
const { operation_id, error, fact } = messageData
142+
new Notification({
143+
title: "Memory Operation Error!",
144+
body: `Memory operation (ID: ${operation_id}) encountered an error.\nError: ${error}\nFact: ${fact.substring(0, 100)}...` // Limit fact preview
145+
}).show()
146+
} else if (messageData.type === "new_message") {
147+
const { message } = messageData
148+
console.log("New message received:", message)
149+
new Notification({
150+
title: "New Message!",
151+
body: message.substring(0, 100) + "..." // Show a preview of the message
152+
}).show()
134153
}
135154
}
136155

src/memory.db

64 KB
Binary file not shown.

src/model/app/app.py

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77
import pickle
88
import multiprocessing
99
import requests
10-
from datetime import datetime, timezone, timedelta
11-
from tzlocal import get_localzone
10+
from datetime import datetime, timezone
1211
from fastapi import FastAPI, HTTPException
1312
from fastapi.responses import JSONResponse, StreamingResponse
1413
from fastapi.middleware.cors import CORSMiddleware
1514
from pydantic import BaseModel
16-
from typing import Optional, Any, Dict, List, AsyncGenerator
15+
from typing import Optional, Any, Dict, List
1716
from neo4j import GraphDatabase
1817
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
1918
from google_auth_oauthlib.flow import InstalledAppFlow
@@ -37,7 +36,6 @@
3736
from model.memory.constants import *
3837
from model.memory.formats import *
3938
from model.memory.backend import MemoryBackend
40-
from model.memory.dual_memory import MemoryManager
4139

4240
from model.utils.helpers import *
4341

@@ -57,6 +55,9 @@
5755
from model.chat.prompts import *
5856
from model.chat.functions import *
5957

58+
from model.context.gmail import GmailContextEngine
59+
from model.context.internet import InternetSearchContextEngine
60+
from model.context.gcalendar import GCalendarContextEngine
6061

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

80+
class WebSocketManager:
81+
def __init__(self):
82+
self.active_connections: List[WebSocket] = []
83+
84+
async def connect(self, websocket: WebSocket):
85+
await websocket.accept()
86+
self.active_connections.append(websocket)
87+
88+
def disconnect(self, websocket: WebSocket):
89+
self.active_connections.remove(websocket)
90+
91+
async def send_personal_message(self, message: str, websocket: WebSocket):
92+
await websocket.send_text(message)
93+
94+
async def broadcast(self, message: str):
95+
for connection in self.active_connections:
96+
try:
97+
await connection.send_text(message)
98+
except Exception as e:
99+
print(f"Error broadcasting message to connection: {e}")
100+
self.disconnect(connection) # Remove broken connection
101+
79102
manager = WebSocketManager()
80103

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

256-
class WebSocketManager:
257-
def __init__(self):
258-
self.active_connections: List[WebSocket] = []
259-
260-
async def connect(self, websocket: WebSocket):
261-
await websocket.accept()
262-
self.active_connections.append(websocket)
263-
264-
def disconnect(self, websocket: WebSocket):
265-
self.active_connections.remove(websocket)
266-
267-
async def send_personal_message(self, message: str, websocket: WebSocket):
268-
await websocket.send_text(message)
269-
270-
async def broadcast(self, message: str):
271-
for connection in self.active_connections:
272-
try:
273-
await connection.send_text(message)
274-
except Exception as e:
275-
print(f"Error broadcasting message to connection: {e}")
276-
self.disconnect(connection) # Remove broken connection
277-
278279
async def cleanup_tasks_periodically():
279280
"""Periodically clean up old completed tasks."""
280281
while True:
@@ -333,7 +334,6 @@ async def process_memory_operations():
333334
while True:
334335
operation = await memory_backend.memory_queue.get_next_operation()
335336

336-
print(f"Processing memory operation: {operation}")
337337
if operation:
338338
try:
339339
user_id = operation["user_id"]
@@ -518,6 +518,20 @@ async def startup_event():
518518
asyncio.create_task(process_queue())
519519
asyncio.create_task(process_memory_operations())
520520
asyncio.create_task(cleanup_tasks_periodically())
521+
522+
user_id = "user1" # Replace with dynamic user ID retrieval if needed
523+
enabled_data_sources = ["gmail", "internet_search", "gcalendar"] # Add gcalendar here
524+
525+
for source in enabled_data_sources:
526+
if source == "gmail":
527+
engine = GmailContextEngine(user_id, task_queue, memory_backend, manager, db_lock)
528+
elif source == "internet_search":
529+
engine = InternetSearchContextEngine(user_id, task_queue, memory_backend, manager, db_lock)
530+
elif source == "gcalendar":
531+
engine = GCalendarContextEngine(user_id, task_queue, memory_backend, manager, db_lock)
532+
else:
533+
continue # Skip unrecognized sources
534+
asyncio.create_task(engine.start())
521535

522536
@app.on_event("shutdown")
523537
async def shutdown_event():

src/model/app/helpers.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,3 +361,30 @@ def write_to_log(message: str):
361361
f"Error writing to log file: {error}"
362362
) # Print error message if writing to log file fails
363363

364+
CHAT_DB = "chatsDb.json"
365+
initial_db = {
366+
"chats": [],
367+
"active_chat_id": None,
368+
"next_chat_id": 1
369+
}
370+
371+
async def load_db():
372+
"""Load the database from chatsDb.json, initializing if it doesn't exist or is invalid."""
373+
try:
374+
with open(CHAT_DB, 'r', encoding='utf-8') as f:
375+
data = json.load(f)
376+
if "chats" not in data:
377+
data["chats"] = []
378+
if "active_chat_id" not in data:
379+
data["active_chat_id"] = None
380+
if "next_chat_id" not in data:
381+
data["next_chat_id"] = 1
382+
return data
383+
except (FileNotFoundError, json.JSONDecodeError):
384+
print("DB NOT FOUND! Initializing with default structure.")
385+
return initial_db
386+
387+
async def save_db(data):
388+
"""Save the data to chatsDb.json."""
389+
with open(CHAT_DB, 'w', encoding='utf-8') as f:
390+
json.dump(data, f, indent=4)

src/model/common/prompts.py

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -344,49 +344,84 @@
344344
"""
345345

346346
internet_summary_system_prompt_template = """
347-
You are tasked with summarizing a list of search results provided as plain strings into a concise, coherent, and unstructured paragraph.
347+
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.
348348
349349
### Instructions:
350-
1. Combine all the results into a single paragraph that captures the key points across all the items.
350+
1. Combine information from the "title" and "description" of each search result into a single paragraph that captures the key points across all items.
351351
2. Avoid repeating information but ensure no important detail is omitted.
352352
3. Maintain a neutral and professional tone.
353353
4. Do not list the results as individual items; instead, weave them seamlessly into a cohesive narrative.
354354
5. Use appropriate transitions to link related points.
355355
6. Avoid directly quoting unless necessary for clarity or emphasis.
356+
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.
357+
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.
356358
357359
### Input Format:
358-
- A simple list of strings, where each string represents a search result or description.
360+
- A list of dictionaries, where each dictionary represents a search result and contains the keys: "title", "url", and "description".
359361
360362
### Output Format:
361-
- A single unstructured paragraph that summarizes the key points from the input.
363+
- A single unstructured paragraph that summarizes the key points from the input, incorporating relevant URLs.
362364
363365
### Examples:
364366
365367
#### Example 1:
366368
Input:
367369
[
368-
"Climate change is causing rising temperatures worldwide.",
369-
"Polar regions are experiencing faster ice melting due to global warming.",
370-
"Melting ice is contributing to rising sea levels, threatening coastal areas."
370+
{"title": "Climate change is causing rising temperatures worldwide.", "url": "url1", "description": "Global warming is leading to increased temperatures across the planet."},
371+
{"title": "Polar regions are experiencing faster ice melting.", "url": "url2", "description": "Due to global warming, ice is melting rapidly in polar areas."},
372+
{"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."}
371373
]
372374
373375
Output:
374-
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.
376+
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).
375377
376378
#### Example 2:
377379
Input:
378380
[
379-
"A balanced diet includes fruits, vegetables, proteins, and whole grains.",
380-
"Staying hydrated is crucial for maintaining overall health.",
381-
"Regular exercise improves cardiovascular health and mental well-being."
381+
{"title": "Balanced diet includes fruits, vegetables.", "url": "url4", "description": "A healthy diet should consist of fruits and vegetables."},
382+
{"title": "Hydration is crucial for health.", "url": "url5", "description": "Staying hydrated is very important for maintaining good health."},
383+
{"title": "Exercise improves cardiovascular health.", "url": "url6", "description": "Regular physical activity benefits the heart and blood vessels."}
382384
]
383385
384386
Output:
385-
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.
387+
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).
388+
389+
#### Example 3:
390+
Input:
391+
[
392+
{
393+
"title": "Breaking News, Latest News and Videos | CNN",
394+
"url": "https://www.cnn.com/",
395+
"description": "View the latest news and breaking news today for U.S., world, weather, entertainment, politics and health at CNN.com."
396+
},
397+
{
398+
"title": "Fox News - Breaking News Updates | Latest News Headlines | Photos & News Videos",
399+
"url": "https://www.foxnews.com/",
400+
"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"
401+
},
402+
{
403+
"title": "NBC News - Breaking News & Top Stories - Latest World, US & Local News | NBC News",
404+
"url": "https://www.nbcnews.com/",
405+
"description": "Go to NBCNews.com for breaking news, videos, and the latest top stories in world news, business, politics, health and pop culture."
406+
},
407+
{
408+
"title": "Associated Press News: Breaking News, Latest Headlines and Videos | AP News",
409+
"url": "https://apnews.com/",
410+
"description": "Read the latest headlines, breaking news, and videos at APNews.com, the definitive source for independent journalism from every corner of the globe."
411+
},
412+
{
413+
"title": "Google News",
414+
"url": "https://news.google.com/",
415+
"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."
416+
}
417+
]
418+
419+
Output:
420+
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.
386421
"""
387422

388-
internet_summary_user_prompt_template = """Summarize the provided list of search results into a single, coherent paragraph.
423+
internet_summary_user_prompt_template = """Summarize the provided list of search results into a single, coherent paragraph, including relevant source URLs.
389424
390425
391426
{query}
392-
"""
427+
"""

0 commit comments

Comments
 (0)