Commit
·
efe51c1
1
Parent(s):
5057a0d
With UI changes and Server Fixes
Browse files- README.md +41 -10
- app.py +59 -18
- llm_parser.py +51 -19
- notion_handler.py +90 -37
- requirements.txt +5 -5
README.md
CHANGED
|
@@ -11,22 +11,53 @@ pinned: false
|
|
| 11 |
|
| 12 |
# 🧠 NotionTaskSense
|
| 13 |
|
| 14 |
-
|
| 15 |
|
| 16 |
-
##
|
| 17 |
|
| 18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
|
| 20 |
-
|
| 21 |
|
| 22 |
-
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
-
|
| 25 |
-
✅ Break it into clear tasks
|
| 26 |
-
✅ Add categories, priorities, due dates
|
| 27 |
-
✅ Push each task into a clean Notion database
|
| 28 |
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
---
|
| 32 |
|
|
|
|
| 11 |
|
| 12 |
# 🧠 NotionTaskSense
|
| 13 |
|
| 14 |
+
NotionTaskSense is an AI-powered tool that helps you organize your goals into structured tasks in Notion. It uses natural language processing to break down your goals into actionable tasks and automatically creates them in your Notion workspace.
|
| 15 |
|
| 16 |
+
## Features
|
| 17 |
|
| 18 |
+
- 🤖 AI-powered task breakdown
|
| 19 |
+
- 📝 Automatic Notion task creation
|
| 20 |
+
- 🎯 Smart task organization
|
| 21 |
+
- 🔄 Real-time processing
|
| 22 |
+
- 🌐 API access available
|
| 23 |
|
| 24 |
+
## How to Use
|
| 25 |
|
| 26 |
+
1. Enter your goals or tasks in natural language
|
| 27 |
+
2. The AI will analyze and break them down into structured tasks
|
| 28 |
+
3. Tasks are automatically created in your Notion workspace
|
| 29 |
+
4. Access your organized tasks in Notion
|
| 30 |
|
| 31 |
+
## API Usage
|
|
|
|
|
|
|
|
|
|
| 32 |
|
| 33 |
+
You can also use NotionTaskSense via its API endpoint:
|
| 34 |
+
|
| 35 |
+
```bash
|
| 36 |
+
curl -X POST http://your-space-url/api/predict \
|
| 37 |
+
-H "Content-Type: application/json" \
|
| 38 |
+
-d '{"data": ["Your task description here"], "fn_index": 0}'
|
| 39 |
+
```
|
| 40 |
+
|
| 41 |
+
## Environment Variables Required
|
| 42 |
+
|
| 43 |
+
- `ANTHROPIC_API_KEY`: Your Anthropic API key for Claude
|
| 44 |
+
- `NOTION_API_KEY`: Your Notion integration token
|
| 45 |
+
- `NOTION_DATABASE_ID`: (Optional) Default Notion database ID
|
| 46 |
+
|
| 47 |
+
## Local Development
|
| 48 |
+
|
| 49 |
+
1. Clone the repository
|
| 50 |
+
2. Install dependencies: `pip install -r requirements.txt`
|
| 51 |
+
3. Set up environment variables
|
| 52 |
+
4. Run the app: `python app.py`
|
| 53 |
+
|
| 54 |
+
## Deployment
|
| 55 |
+
|
| 56 |
+
This app is deployed on Hugging Face Spaces and can be accessed at [space-url].
|
| 57 |
+
|
| 58 |
+
## License
|
| 59 |
+
|
| 60 |
+
MIT License
|
| 61 |
|
| 62 |
---
|
| 63 |
|
app.py
CHANGED
|
@@ -1,39 +1,80 @@
|
|
| 1 |
import gradio as gr
|
| 2 |
import os
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
from llm_parser import llm_parse_tasks
|
| 5 |
from notion_handler import create_tasks_database, push_tasks_to_notion
|
| 6 |
|
| 7 |
-
def organize_goals_into_notion(user_input: str) -> str:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
try:
|
|
|
|
| 9 |
tasks = llm_parse_tasks(user_input)
|
| 10 |
if isinstance(tasks, str):
|
| 11 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
|
| 13 |
db_id = create_tasks_database()
|
| 14 |
push_tasks_to_notion(tasks, db_id)
|
| 15 |
|
| 16 |
task_names = [t.get("task", "Untitled") for t in tasks]
|
| 17 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 18 |
except Exception as e:
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
-
# Gradio
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
|
| 27 |
-
#
|
| 28 |
-
|
|
|
|
|
|
|
|
|
|
| 29 |
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
|
|
|
| 35 |
|
| 36 |
|
| 37 |
|
| 38 |
-
if __name__ == "__main__":
|
| 39 |
-
demo.launch()
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
import os
|
| 3 |
+
from typing import Dict, List, Union, Any
|
| 4 |
+
import logging
|
| 5 |
+
|
| 6 |
+
# Configure logging
|
| 7 |
+
logging.basicConfig(level=logging.INFO)
|
| 8 |
+
logger = logging.getLogger(__name__)
|
| 9 |
|
| 10 |
from llm_parser import llm_parse_tasks
|
| 11 |
from notion_handler import create_tasks_database, push_tasks_to_notion
|
| 12 |
|
| 13 |
+
def organize_goals_into_notion(user_input: str) -> Dict[str, Any]:
|
| 14 |
+
"""
|
| 15 |
+
Process a single goal into Notion tasks.
|
| 16 |
+
Returns a dictionary with success status and detailed response.
|
| 17 |
+
"""
|
| 18 |
try:
|
| 19 |
+
logger.info(f"Processing user input: {user_input}")
|
| 20 |
tasks = llm_parse_tasks(user_input)
|
| 21 |
if isinstance(tasks, str):
|
| 22 |
+
logger.error(f"Failed to parse tasks: {tasks}")
|
| 23 |
+
return {
|
| 24 |
+
"success": False,
|
| 25 |
+
"error": "Failed to parse tasks",
|
| 26 |
+
"details": tasks
|
| 27 |
+
}
|
| 28 |
|
| 29 |
db_id = create_tasks_database()
|
| 30 |
push_tasks_to_notion(tasks, db_id)
|
| 31 |
|
| 32 |
task_names = [t.get("task", "Untitled") for t in tasks]
|
| 33 |
+
logger.info(f"Successfully created {len(task_names)} tasks")
|
| 34 |
+
return {
|
| 35 |
+
"success": True,
|
| 36 |
+
"message": f"✅ {len(task_names)} tasks added to Notion",
|
| 37 |
+
"tasks": task_names,
|
| 38 |
+
"database_id": db_id
|
| 39 |
+
}
|
| 40 |
except Exception as e:
|
| 41 |
+
logger.error(f"Error processing request: {str(e)}")
|
| 42 |
+
return {
|
| 43 |
+
"success": False,
|
| 44 |
+
"error": str(e),
|
| 45 |
+
"details": "An error occurred while processing your request"
|
| 46 |
+
}
|
| 47 |
|
| 48 |
+
# Create Gradio interface
|
| 49 |
+
demo = gr.Interface(
|
| 50 |
+
fn=organize_goals_into_notion,
|
| 51 |
+
inputs=gr.Textbox(
|
| 52 |
+
lines=4,
|
| 53 |
+
placeholder="What do you want to get done this week?",
|
| 54 |
+
label="Your Goals"
|
| 55 |
+
),
|
| 56 |
+
outputs=gr.JSON(label="Results"),
|
| 57 |
+
title="🧠 NotionTaskSense",
|
| 58 |
+
description="Turn your goals into structured Notion tasks",
|
| 59 |
+
examples=[
|
| 60 |
+
["I need to update my resume, apply to 3 jobs, and study for AWS certification"],
|
| 61 |
+
["Meet with team about project timeline, prepare presentation for client, and follow up on pending emails"],
|
| 62 |
+
],
|
| 63 |
+
theme=gr.themes.Soft()
|
| 64 |
+
)
|
| 65 |
|
| 66 |
+
# Add MCP metadata
|
| 67 |
+
organize_goals_into_notion.mcp_type = "tool"
|
| 68 |
+
organize_goals_into_notion.mcp_description = "Organize goals into structured Notion tasks"
|
| 69 |
+
organize_goals_into_notion.mcp_input_type = "string"
|
| 70 |
+
organize_goals_into_notion.mcp_output_type = "json"
|
| 71 |
|
| 72 |
+
if __name__ == "__main__":
|
| 73 |
+
demo.queue().launch(
|
| 74 |
+
server_name="0.0.0.0",
|
| 75 |
+
server_port=7860,
|
| 76 |
+
share=False
|
| 77 |
+
)
|
| 78 |
|
| 79 |
|
| 80 |
|
|
|
|
|
|
llm_parser.py
CHANGED
|
@@ -1,40 +1,72 @@
|
|
| 1 |
import anthropic
|
| 2 |
import os
|
| 3 |
import json
|
|
|
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
|
| 6 |
load_dotenv() # Load environment variables from .env file
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
|
| 9 |
|
| 10 |
-
def llm_parse_tasks(user_input):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
prompt = f"""
|
| 12 |
You are a helpful assistant that turns vague personal goals into clear, actionable tasks.
|
| 13 |
|
| 14 |
Break this input into tasks with:
|
| 15 |
-
- task name
|
| 16 |
-
- category (Career, Learning, Personal, Outreach,
|
| 17 |
-
- priority (High, Medium, Low
|
| 18 |
-
- optional due date (if mentioned or inferred
|
| 19 |
-
-
|
| 20 |
|
| 21 |
-
Return
|
|
|
|
| 22 |
|
| 23 |
Input: \"\"\"{user_input}\"\"\"
|
| 24 |
"""
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
| 37 |
-
|
| 38 |
-
|
|
|
|
| 39 |
except json.JSONDecodeError:
|
| 40 |
-
return
|
|
|
|
|
|
|
|
|
| 1 |
import anthropic
|
| 2 |
import os
|
| 3 |
import json
|
| 4 |
+
from typing import List, Dict, Union, Any
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
|
| 7 |
load_dotenv() # Load environment variables from .env file
|
| 8 |
|
| 9 |
+
# Check for required environment variables
|
| 10 |
+
if not os.getenv("ANTHROPIC_API_KEY"):
|
| 11 |
+
raise ValueError("ANTHROPIC_API_KEY environment variable is not set")
|
| 12 |
+
|
| 13 |
client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY"))
|
| 14 |
|
| 15 |
+
def llm_parse_tasks(user_input: str) -> Union[List[Dict[str, Any]], str]:
|
| 16 |
+
"""
|
| 17 |
+
Parse user input into structured tasks using Claude 3.
|
| 18 |
+
|
| 19 |
+
Args:
|
| 20 |
+
user_input (str): The user's natural language input describing their goals
|
| 21 |
+
|
| 22 |
+
Returns:
|
| 23 |
+
Union[List[Dict[str, Any]], str]: Either a list of task dictionaries or an error message
|
| 24 |
+
"""
|
| 25 |
prompt = f"""
|
| 26 |
You are a helpful assistant that turns vague personal goals into clear, actionable tasks.
|
| 27 |
|
| 28 |
Break this input into tasks with:
|
| 29 |
+
- task name (key: "task")
|
| 30 |
+
- category (key: "category") - Choose from: Career, Learning, Personal, Outreach, Health, Finance
|
| 31 |
+
- priority (key: "priority") - Choose from: High, Medium, Low
|
| 32 |
+
- optional due date (key: "dueDate") - Use ISO format YYYY-MM-DD if date is mentioned or inferred
|
| 33 |
+
- notes (key: "notes") - Add relevant context or subtasks
|
| 34 |
|
| 35 |
+
Return ONLY a valid JSON array of task objects with the exact keys mentioned above.
|
| 36 |
+
Each task MUST have at least task, category, and priority fields.
|
| 37 |
|
| 38 |
Input: \"\"\"{user_input}\"\"\"
|
| 39 |
"""
|
| 40 |
|
| 41 |
+
try:
|
| 42 |
+
response = client.messages.create(
|
| 43 |
+
model="claude-3-haiku-20240307",
|
| 44 |
+
max_tokens=1024,
|
| 45 |
+
temperature=0.4,
|
| 46 |
+
messages=[
|
| 47 |
+
{"role": "user", "content": prompt}
|
| 48 |
+
]
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
content = response.content[0].text.strip()
|
| 52 |
+
tasks = json.loads(content)
|
| 53 |
|
| 54 |
+
# Validate required fields
|
| 55 |
+
for task in tasks:
|
| 56 |
+
if not all(k in task for k in ["task", "category", "priority"]):
|
| 57 |
+
return "Error: Each task must have task, category, and priority fields"
|
| 58 |
+
|
| 59 |
+
# Validate category and priority values
|
| 60 |
+
if task["category"] not in ["Career", "Learning", "Personal", "Outreach", "Health", "Finance"]:
|
| 61 |
+
return f"Error: Invalid category '{task['category']}' in task '{task['task']}'"
|
| 62 |
+
|
| 63 |
+
if task["priority"] not in ["High", "Medium", "Low"]:
|
| 64 |
+
return f"Error: Invalid priority '{task['priority']}' in task '{task['task']}'"
|
| 65 |
|
| 66 |
+
return tasks
|
| 67 |
+
except anthropic.APIError as e:
|
| 68 |
+
return f"Claude API Error: {str(e)}"
|
| 69 |
except json.JSONDecodeError:
|
| 70 |
+
return "Error: Failed to parse Claude's response as JSON"
|
| 71 |
+
except Exception as e:
|
| 72 |
+
return f"Unexpected error: {str(e)}"
|
notion_handler.py
CHANGED
|
@@ -1,50 +1,103 @@
|
|
| 1 |
import os
|
|
|
|
| 2 |
from notion_client import Client
|
| 3 |
from datetime import datetime
|
| 4 |
from dotenv import load_dotenv
|
| 5 |
|
| 6 |
load_dotenv() # Load environment variables from .env file
|
| 7 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
notion = Client(auth=os.getenv("NOTION_TOKEN"))
|
| 9 |
parent_page_id = os.getenv("NOTION_PARENT_PAGE_ID")
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
properties["Due Date"] = {"date": {"start": task["dueDate"]}}
|
| 41 |
-
except:
|
| 42 |
-
pass
|
| 43 |
|
| 44 |
-
|
| 45 |
-
|
| 46 |
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
+
from typing import List, Dict, Any
|
| 3 |
from notion_client import Client
|
| 4 |
from datetime import datetime
|
| 5 |
from dotenv import load_dotenv
|
| 6 |
|
| 7 |
load_dotenv() # Load environment variables from .env file
|
| 8 |
|
| 9 |
+
# Check for required environment variables
|
| 10 |
+
if not os.getenv("NOTION_TOKEN"):
|
| 11 |
+
raise ValueError("NOTION_TOKEN environment variable is not set")
|
| 12 |
+
if not os.getenv("NOTION_PARENT_PAGE_ID"):
|
| 13 |
+
raise ValueError("NOTION_PARENT_PAGE_ID environment variable is not set")
|
| 14 |
+
|
| 15 |
notion = Client(auth=os.getenv("NOTION_TOKEN"))
|
| 16 |
parent_page_id = os.getenv("NOTION_PARENT_PAGE_ID")
|
| 17 |
|
| 18 |
+
def create_tasks_database() -> str:
|
| 19 |
+
"""
|
| 20 |
+
Create a new Notion database for tasks.
|
| 21 |
+
|
| 22 |
+
Returns:
|
| 23 |
+
str: The ID of the created database
|
| 24 |
+
|
| 25 |
+
Raises:
|
| 26 |
+
Exception: If database creation fails
|
| 27 |
+
"""
|
| 28 |
+
try:
|
| 29 |
+
response = notion.databases.create(
|
| 30 |
+
parent={"type": "page_id", "page_id": parent_page_id},
|
| 31 |
+
title=[{"type": "text", "text": {"content": f"NotionTaskSense Tasks - {datetime.now().strftime('%Y-%m-%d')}"}}],
|
| 32 |
+
properties={
|
| 33 |
+
"Task": {"title": {}},
|
| 34 |
+
"Category": {
|
| 35 |
+
"select": {
|
| 36 |
+
"options": [
|
| 37 |
+
{"name": "Career", "color": "blue"},
|
| 38 |
+
{"name": "Learning", "color": "green"},
|
| 39 |
+
{"name": "Personal", "color": "orange"},
|
| 40 |
+
{"name": "Outreach", "color": "purple"},
|
| 41 |
+
{"name": "Health", "color": "red"},
|
| 42 |
+
{"name": "Finance", "color": "yellow"}
|
| 43 |
+
]
|
| 44 |
+
}
|
| 45 |
+
},
|
| 46 |
+
"Priority": {
|
| 47 |
+
"select": {
|
| 48 |
+
"options": [
|
| 49 |
+
{"name": "High", "color": "red"},
|
| 50 |
+
{"name": "Medium", "color": "yellow"},
|
| 51 |
+
{"name": "Low", "color": "blue"}
|
| 52 |
+
]
|
| 53 |
+
}
|
| 54 |
+
},
|
| 55 |
+
"Due Date": {"date": {}},
|
| 56 |
+
"Status": {
|
| 57 |
+
"select": {
|
| 58 |
+
"options": [
|
| 59 |
+
{"name": "To Do", "color": "gray"},
|
| 60 |
+
{"name": "In Progress", "color": "blue"},
|
| 61 |
+
{"name": "Done", "color": "green"}
|
| 62 |
+
]
|
| 63 |
+
}
|
| 64 |
+
},
|
| 65 |
+
"Notes": {"rich_text": {}}
|
| 66 |
+
}
|
| 67 |
+
)
|
| 68 |
+
return response["id"]
|
| 69 |
+
except Exception as e:
|
| 70 |
+
raise Exception(f"Failed to create Notion database: {str(e)}")
|
| 71 |
+
|
| 72 |
+
def push_tasks_to_notion(tasks: List[Dict[str, Any]], db_id: str) -> None:
|
| 73 |
+
"""
|
| 74 |
+
Add or update tasks in the Notion database.
|
| 75 |
+
|
| 76 |
+
Args:
|
| 77 |
+
tasks (List[Dict[str, Any]]): List of task dictionaries
|
| 78 |
+
db_id (str): Notion database ID
|
| 79 |
+
|
| 80 |
+
Raises:
|
| 81 |
+
Exception: If pushing tasks fails
|
| 82 |
+
"""
|
| 83 |
+
try:
|
| 84 |
+
for task in tasks:
|
| 85 |
+
properties = {
|
| 86 |
+
"Task": {"title": [{"text": {"content": task.get("task", "Untitled Task")}}]},
|
| 87 |
+
"Category": {"select": {"name": task.get("category", "Personal")}},
|
| 88 |
+
"Priority": {"select": {"name": task.get("priority", "Medium")}},
|
| 89 |
+
"Status": {"select": {"name": "To Do"}},
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
if "dueDate" in task and task["dueDate"]:
|
| 93 |
properties["Due Date"] = {"date": {"start": task["dueDate"]}}
|
|
|
|
|
|
|
| 94 |
|
| 95 |
+
if "notes" in task and task["notes"]:
|
| 96 |
+
properties["Notes"] = {"rich_text": [{"text": {"content": task["notes"]}}]}
|
| 97 |
|
| 98 |
+
notion.pages.create(
|
| 99 |
+
parent={"database_id": db_id},
|
| 100 |
+
properties=properties
|
| 101 |
+
)
|
| 102 |
+
except Exception as e:
|
| 103 |
+
raise Exception(f"Failed to push tasks to Notion: {str(e)}")
|
requirements.txt
CHANGED
|
@@ -7,11 +7,11 @@ charset-normalizer==3.4.2
|
|
| 7 |
click==8.2.1
|
| 8 |
distro==1.9.0
|
| 9 |
exceptiongroup==1.3.0
|
| 10 |
-
fastapi
|
| 11 |
ffmpy==0.6.0
|
| 12 |
filelock==3.18.0
|
| 13 |
fsspec==2025.5.1
|
| 14 |
-
gradio
|
| 15 |
gradio_client==1.10.2
|
| 16 |
groovy==0.1.2
|
| 17 |
h11==0.16.0
|
|
@@ -25,7 +25,7 @@ jiter==0.10.0
|
|
| 25 |
markdown-it-py==3.0.0
|
| 26 |
MarkupSafe==3.0.2
|
| 27 |
mdurl==0.1.2
|
| 28 |
-
notion-client
|
| 29 |
numpy==2.2.6
|
| 30 |
openai==1.85.0
|
| 31 |
orjson==3.10.18
|
|
@@ -37,7 +37,7 @@ pydantic_core==2.33.2
|
|
| 37 |
pydub==0.25.1
|
| 38 |
Pygments==2.19.1
|
| 39 |
python-dateutil==2.9.0.post0
|
| 40 |
-
python-dotenv
|
| 41 |
python-multipart==0.0.20
|
| 42 |
pytz==2025.2
|
| 43 |
PyYAML==6.0.2
|
|
@@ -57,5 +57,5 @@ typing-inspection==0.4.1
|
|
| 57 |
typing_extensions==4.14.0
|
| 58 |
tzdata==2025.2
|
| 59 |
urllib3==2.4.0
|
| 60 |
-
uvicorn
|
| 61 |
websockets==15.0.1
|
|
|
|
| 7 |
click==8.2.1
|
| 8 |
distro==1.9.0
|
| 9 |
exceptiongroup==1.3.0
|
| 10 |
+
fastapi>=0.110.0
|
| 11 |
ffmpy==0.6.0
|
| 12 |
filelock==3.18.0
|
| 13 |
fsspec==2025.5.1
|
| 14 |
+
gradio>=4.19.2
|
| 15 |
gradio_client==1.10.2
|
| 16 |
groovy==0.1.2
|
| 17 |
h11==0.16.0
|
|
|
|
| 25 |
markdown-it-py==3.0.0
|
| 26 |
MarkupSafe==3.0.2
|
| 27 |
mdurl==0.1.2
|
| 28 |
+
notion-client>=2.2.1
|
| 29 |
numpy==2.2.6
|
| 30 |
openai==1.85.0
|
| 31 |
orjson==3.10.18
|
|
|
|
| 37 |
pydub==0.25.1
|
| 38 |
Pygments==2.19.1
|
| 39 |
python-dateutil==2.9.0.post0
|
| 40 |
+
python-dotenv>=1.0.1
|
| 41 |
python-multipart==0.0.20
|
| 42 |
pytz==2025.2
|
| 43 |
PyYAML==6.0.2
|
|
|
|
| 57 |
typing_extensions==4.14.0
|
| 58 |
tzdata==2025.2
|
| 59 |
urllib3==2.4.0
|
| 60 |
+
uvicorn>=0.27.1
|
| 61 |
websockets==15.0.1
|