diff --git a/backend/app/main.py b/backend/app/main.py index ac9c7b2918fa444aaa85a7fca0091552beb2b841..45496391af06cfde03255c5fc801558f36b5bce7 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -28,6 +28,7 @@ import config from security import jwt_cookie, get_jwt_user from routes.tests import testRouter from routes.studies import studiesRouter +from routes.chat import chatRouter websocket_users = defaultdict(lambda: defaultdict(set)) websocket_users_global = defaultdict(set) @@ -1057,5 +1058,6 @@ v1Router.include_router(studyRouter) v1Router.include_router(websocketRouter) v1Router.include_router(testRouter) v1Router.include_router(studiesRouter) +v1Router.include_router(chatRouter) apiRouter.include_router(v1Router) app.include_router(apiRouter) diff --git a/backend/app/routes/chat.py b/backend/app/routes/chat.py new file mode 100644 index 0000000000000000000000000000000000000000..9222de206ecd9587192ad02289b17badb17c10f6 --- /dev/null +++ b/backend/app/routes/chat.py @@ -0,0 +1,57 @@ +from fastapi import APIRouter, HTTPException, Depends +from pydantic import BaseModel +import requests +import os +from dotenv import load_dotenv + +# Load API key from .env +load_dotenv() +API_KEY = os.getenv("OPENROUTER_API_KEY") + +# Mistral API details +MODEL_NAME = "mistralai/mistral-small-24b-instruct-2501:free" +API_URL = "https://openrouter.ai/api/v1/chat/completions" + +# Initialize FastAPI router +chatRouter = APIRouter(prefix="/chat", tags=["chat"]) + +# Message schema +class ChatMessage(BaseModel): + session_id: str + role: str + content: str + +# Temporary chat history storage +chat_sessions = {} + +@chatRouter.post("/") +async def chat_with_ai(message: ChatMessage): + session_id = message.session_id + user_message = {"role": message.role, "content": message.content} + + # Store chat history per session + if session_id not in chat_sessions: + chat_sessions[session_id] = [] + + chat_sessions[session_id].append(user_message) + + # Prepare request + headers = { + "Authorization": f"Bearer {API_KEY}", + "Content-Type": "application/json" + } + + data = { + "model": MODEL_NAME, + "messages": chat_sessions[session_id] + } + + # Call Mistral AI + response = requests.post(API_URL, headers=headers, json=data) + + if response.status_code == 200: + bot_response = response.json()["choices"][0]["message"]["content"] + chat_sessions[session_id].append({"role": "assistant", "content": bot_response}) + return {"response": bot_response} + else: + raise HTTPException(status_code=response.status_code, detail=response.text) diff --git a/backend/requirements.txt b/backend/requirements.txt index b1a43b0a21db07ac0c0fdc136c874c25c90706a7..9eb2045946b35bf2cd227dc74c67c30296d7937a 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,7 +1,43 @@ -uvicorn[standard]>=0.27.0,<0.28.0 -fastapi>=0.110.0,<0.111.0 -fastapi_jwt>=0.2.0,<0.3.0 -sqlalchemy>=2.0.0,<2.1.0 -passlib>=1.7.0,<1.8.0 -python-jose>=3.3.0,<3.4.0 -python-multipart>=0.0.0,<0.1.0 +alembic==1.14.1 +annotated-types==0.7.0 +anyio==4.7.0 +bcrypt==3.2.0 +black==24.10.0 +certifi==2025.1.31 +cffi==1.17.1 +charset-normalizer==3.4.1 +click==8.1.7 +cryptography==44.0.0 +ecdsa==0.19.0 +fastapi==0.110.3 +fastapi-jwt==0.2.0 +h11==0.14.0 +httptools==0.6.4 +idna==3.10 +Mako==1.3.9 +MarkupSafe==3.0.2 +mypy-extensions==1.0.0 +packaging==24.2 +passlib==1.7.4 +pathspec==0.12.1 +platformdirs==4.3.6 +pyasn1==0.6.1 +pycparser==2.22 +pydantic==2.10.3 +pydantic_core==2.27.1 +python-dotenv==1.0.1 +python-jose==3.3.0 +python-multipart==0.0.19 +PyYAML==6.0.2 +requests==2.32.3 +rsa==4.9 +six==1.17.0 +sniffio==1.3.1 +SQLAlchemy==2.0.36 +starlette==0.37.2 +typing_extensions==4.12.2 +urllib3==2.3.0 +uvicorn==0.27.1 +uvloop==0.21.0 +watchfiles==1.0.3 +websockets==14.1