diff --git a/sunbird-ai-assistant/.env.example b/sunbird-ai-assistant/.env.example new file mode 100644 index 00000000..8cadcda9 --- /dev/null +++ b/sunbird-ai-assistant/.env.example @@ -0,0 +1,5 @@ +SUNBIRD_BASE_URL=https://dev.sunbird.org/api +SUNBIRD_AUTH_TOKEN=your_bearer_token_here +DEFAULT_USER_ID=your_test_user_id +LOG_LEVEL=DEBUG +DEFAULT_COURSE_LIMIT=10 diff --git a/sunbird-ai-assistant/README.md b/sunbird-ai-assistant/README.md new file mode 100644 index 00000000..bbb9f73a --- /dev/null +++ b/sunbird-ai-assistant/README.md @@ -0,0 +1,68 @@ +# 🤖 Sunbird AI Assistant + +An intelligent, context-aware AI assistant powered by the Model Context Protocol (MCP), designed to integrate with the Sunbird Ed platform and enhance learning experiences through natural language interaction. + +Built by COSS • Category: AI & Conversational Agents, Education + +--- + +## 🚀 Project Overview + +Sunbird AI Assistant enables conversational access to Sunbird Ed’s powerful learning APIs through a modular AI agent. It allows users to: + +- Query course metadata +- Retrieve enrollment information +- View their profile details +- Leverage deployment-specific context +- Extend toward personalized learning journeys + +--- + +## 🧠 Features + +- **Context-Aware**: The AI assistant is capable of responding based on both installation-level context and user-specific data. +- **Customizable Tools**: Integrates with the Sunbird Ed APIs for fetching course metadata, user enrollments, and profile information. +- **Extensible**: Designed to allow easy integration of additional tools and features. +- **Lightweight UI**: Initially built with a simple CLI interface for easy interaction and testing. + +--- + +## ⚙️ Setup & Installation + +1. **Clone the Repository** + + ```bash + git clone https://github.com/Code4GovTech/C4GT.git + cd C4GT/sunbird-ai-assistant + ``` + +2. **Install Dependencies** + + Make sure you have Python 3.8 or higher installed. + + ```bash + pip install -r requirements.txt + ``` + +3. **Set Up Environment Variables** + + Create a `.env` file in the root of the project and add the following: + + ```dotenv + SUNBIRD_BASE_URL=https://dev.sunbird.org/api + SUNBIRD_AUTH_TOKEN=your_bearer_token_here + DEFAULT_USER_ID=your_test_user_id + LOG_LEVEL=DEBUG + DEFAULT_COURSE_LIMIT=10 + ``` + + > **Note**: Make sure to keep your Bearer Token (`SUNBIRD_AUTH_TOKEN`) secure and do not expose it in your public repository. + +--- + +## 🧪 Running Tests + +Run the integration tests to verify that the AI assistant is correctly interacting with the Sunbird Ed APIs. + +```bash +python -m unittest tests/test_agent.py diff --git a/sunbird-ai-assistant/app/agents/sunbird_agent.py b/sunbird-ai-assistant/app/agents/sunbird_agent.py new file mode 100644 index 00000000..5dcea629 --- /dev/null +++ b/sunbird-ai-assistant/app/agents/sunbird_agent.py @@ -0,0 +1,12 @@ +from openai_mcp_sdk.agent import Agent +from app.tools.course_tool import CourseMetadataTool +from app.tools.enrollment_tool import EnrollmentTool +from app.tools.profile_tool import UserProfileTool + +def build_agent(context: dict) -> Agent: + tools = [ + CourseMetadataTool(), + EnrollmentTool(), + UserProfileTool() + ] + return Agent(tools=tools, initial_context=context) diff --git a/sunbird-ai-assistant/app/context/installation_context.py b/sunbird-ai-assistant/app/context/installation_context.py new file mode 100644 index 00000000..8691be59 --- /dev/null +++ b/sunbird-ai-assistant/app/context/installation_context.py @@ -0,0 +1,7 @@ +def get_installation_context(): + return { + "deployment": "sunbird-dev", + "base_url": "https://dev.sunbird.org/api", + "token": "your-auth-token", # Secure this in production + "features_enabled": ["courses", "progress", "enrollments"] + } diff --git a/sunbird-ai-assistant/app/interface/cli_interface.py b/sunbird-ai-assistant/app/interface/cli_interface.py new file mode 100644 index 00000000..359d657e --- /dev/null +++ b/sunbird-ai-assistant/app/interface/cli_interface.py @@ -0,0 +1,9 @@ +def chat_loop(agent): + print("Sunbird AI Assistant (type 'exit' to quit)\n") + while True: + user_input = input("> ") + if user_input.lower() in ("exit", "quit"): + print("Goodbye!") + break + response = agent.chat(user_input) + print(response) diff --git a/sunbird-ai-assistant/app/tools/course_tool.py b/sunbird-ai-assistant/app/tools/course_tool.py new file mode 100644 index 00000000..9facae35 --- /dev/null +++ b/sunbird-ai-assistant/app/tools/course_tool.py @@ -0,0 +1,15 @@ +def call(self, input_data: dict) -> dict: + url = f"{input_data['base_url']}/course/v1/search" + headers = { + "Authorization": f"Bearer {input_data['token']}", + "Content-Type": "application/json" + } + body = { + "request": { + "filters": input_data.get("filters", {}), + "limit": input_data.get("limit", 10) + } + } + + response = requests.post(url, json=body, headers=headers) + return response.json() diff --git a/sunbird-ai-assistant/app/tools/enrollment_tool.py b/sunbird-ai-assistant/app/tools/enrollment_tool.py new file mode 100644 index 00000000..7b7e3071 --- /dev/null +++ b/sunbird-ai-assistant/app/tools/enrollment_tool.py @@ -0,0 +1,10 @@ +def call(self, input_data: dict) -> dict: + user_id = input_data["user_id"] + url = f"{input_data['base_url']}/user/enrollment/list/{user_id}" + headers = { + "Authorization": f"Bearer {input_data['token']}", + "Content-Type": "application/json" + } + + response = requests.get(url, headers=headers) + return response.json() diff --git a/sunbird-ai-assistant/app/tools/profile_tool.py b/sunbird-ai-assistant/app/tools/profile_tool.py new file mode 100644 index 00000000..0ede9708 --- /dev/null +++ b/sunbird-ai-assistant/app/tools/profile_tool.py @@ -0,0 +1,10 @@ +def call(self, input_data: dict) -> dict: + user_id = input_data["user_id"] + url = f"{input_data['base_url']}/user/v1/profile/{user_id}" + headers = { + "Authorization": f"Bearer {input_data['token']}", + "Content-Type": "application/json" + } + + response = requests.get(url, headers=headers) + return response.json() diff --git a/sunbird-ai-assistant/config/settings.py b/sunbird-ai-assistant/config/settings.py new file mode 100644 index 00000000..a4d3f584 --- /dev/null +++ b/sunbird-ai-assistant/config/settings.py @@ -0,0 +1,20 @@ +import os +from dotenv import load_dotenv + +# Load environment variables from .env file +load_dotenv() + +# Base URL of the Sunbird Ed API deployment +SUNBIRD_BASE_URL = os.getenv("SUNBIRD_BASE_URL", "https://dev.sunbird.org/api") + +# Bearer token or API key for authentication (keep this secure!) +SUNBIRD_AUTH_TOKEN = os.getenv("SUNBIRD_AUTH_TOKEN") + +# Default user ID (for testing or fallback) +DEFAULT_USER_ID = os.getenv("DEFAULT_USER_ID", "replace_with_a_test_user_id") + +# Logging level +LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO") + +# Tool config: default course fetch limit +DEFAULT_COURSE_LIMIT = int(os.getenv("DEFAULT_COURSE_LIMIT", 10)) diff --git a/sunbird-ai-assistant/main.py b/sunbird-ai-assistant/main.py new file mode 100644 index 00000000..487fd3a9 --- /dev/null +++ b/sunbird-ai-assistant/main.py @@ -0,0 +1,22 @@ +from app.agents.sunbird_agent import build_agent +from app.interface.cli_interface import chat_loop +from config.settings import SUNBIRD_BASE_URL, SUNBIRD_AUTH_TOKEN, DEFAULT_USER_ID + +def main(): + print("Initializing Sunbird AI Assistant...") + + # Shared context passed to tools and agent + context = { + "base_url": SUNBIRD_BASE_URL, + "token": SUNBIRD_AUTH_TOKEN, + "user_id": DEFAULT_USER_ID + } + + # Build the agent with context-aware tools + agent = build_agent(context) + + # Start CLI loop + chat_loop(agent) + +if __name__ == "__main__": + main() diff --git a/sunbird-ai-assistant/requirements.txt b/sunbird-ai-assistant/requirements.txt new file mode 100644 index 00000000..b6e98b7c --- /dev/null +++ b/sunbird-ai-assistant/requirements.txt @@ -0,0 +1,12 @@ +# Python core +python-dotenv>=1.0.0 +requests>=2.31.0 + +# MCP SDK (assuming from OpenAI or similar package) +openai-mcp-sdk>=0.1.0 # Replace with the actual package name if different + +# Optional for development and testing +unittest2>=1.1.0 + +# Linting (optional) +flake8>=6.0.0 diff --git a/sunbird-ai-assistant/tests/test_agent.py b/sunbird-ai-assistant/tests/test_agent.py new file mode 100644 index 00000000..24308a8d --- /dev/null +++ b/sunbird-ai-assistant/tests/test_agent.py @@ -0,0 +1,34 @@ +import unittest +from app.agents.sunbird_agent import build_agent +from config.settings import SUNBIRD_BASE_URL, SUNBIRD_AUTH_TOKEN, DEFAULT_USER_ID + +class TestSunbirdAgent(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.context = { + "base_url": SUNBIRD_BASE_URL, + "token": SUNBIRD_AUTH_TOKEN, + "user_id": DEFAULT_USER_ID + } + cls.agent = build_agent(cls.context) + + def test_course_metadata_tool(self): + prompt = "List some available courses" + response = self.agent.chat(prompt) + self.assertIn("result", response) + print("Course Metadata Tool Output:", response) + + def test_enrollment_tool(self): + prompt = "Show my enrolled courses" + response = self.agent.chat(prompt) + self.assertIn("result", response) + print("Enrollment Tool Output:", response) + + def test_profile_tool(self): + prompt = "What is my profile info?" + response = self.agent.chat(prompt) + self.assertIn("result", response) + print("User Profile Tool Output:", response) + +if __name__ == "__main__": + unittest.main()