Sohan Kshirsagar commited on
Commit
c48f478
·
1 Parent(s): 7b6fb1a

Changes to include single model represented as multiple personas

Browse files
README.md CHANGED
@@ -1 +1,3 @@
1
- # Neon-AI-Project
 
 
 
1
+ # Neon-AI-Project
2
+
3
+ Multi-model LLM chatbot.
multi_llm_chatbot_backend/app/__init__.py ADDED
File without changes
multi_llm_chatbot_backend/app/api/routes.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, Body
2
+ from app.llm.mistral_client import MistralClient
3
+ from app.models.persona import Persona
4
+ from app.core.orchestrator import ChatOrchestrator
5
+
6
+ router = APIRouter()
7
+
8
+ # Singleton for now
9
+ llm = MistralClient()
10
+ orchestrator = ChatOrchestrator()
11
+
12
+ # Register initial personas
13
+ orchestrator.register_persona(Persona(
14
+ id="methodist",
15
+ name="Methodist Advisor",
16
+ system_prompt="You are a highly methodical PhD advisor who believes in structure and planning.",
17
+ llm=llm
18
+ ))
19
+
20
+ orchestrator.register_persona(Persona(
21
+ id="theorist",
22
+ name="Theorist Advisor",
23
+ system_prompt="You are a philosophical PhD advisor who focuses on abstract theories and ideas.",
24
+ llm=llm
25
+ ))
26
+
27
+ orchestrator.register_persona(Persona(
28
+ id="pragmatist",
29
+ name="Pragmatist Advisor",
30
+ system_prompt="You are a practical PhD advisor who focuses on real-world outcomes and utility.",
31
+ llm=llm
32
+ ))
33
+
34
+ @router.post("/chat")
35
+ async def chat(
36
+ user_input: str = Body(...),
37
+ active_personas: list[str] = Body(default=["methodist", "theorist", "pragmatist"])
38
+ ):
39
+ orchestrator.set_active_personas(active_personas)
40
+ return await orchestrator.process_user_input(user_input)
multi_llm_chatbot_backend/app/config.py ADDED
File without changes
multi_llm_chatbot_backend/app/core/context.py ADDED
File without changes
multi_llm_chatbot_backend/app/core/orchestrator.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from app.models.persona import Persona
2
+
3
+ class ChatOrchestrator:
4
+ def __init__(self):
5
+ self.history: list[dict] = []
6
+ self.personas: dict[str, Persona] = {}
7
+
8
+ def register_persona(self, persona: Persona):
9
+ self.personas[persona.id] = persona
10
+
11
+ def set_active_personas(self, ids: list[str]):
12
+ self.active_ids = [pid for pid in ids if pid in self.personas]
13
+
14
+ async def process_user_input(self, user_input: str):
15
+ self.history.append({"role": "user", "content": user_input})
16
+ responses = []
17
+
18
+ for pid in self.active_ids:
19
+ persona = self.personas[pid]
20
+ reply = await persona.respond(self.history)
21
+ self.history.append({"role": persona.id, "content": reply})
22
+ responses.append({"persona": persona.name, "response": reply})
23
+
24
+ return responses
multi_llm_chatbot_backend/app/llm/llm_client.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from abc import ABC, abstractmethod
2
+ from typing import List
3
+
4
+ class LLMClient(ABC):
5
+ @abstractmethod
6
+ async def generate(self, system_prompt: str, context: List[dict]) -> str:
7
+ pass
multi_llm_chatbot_backend/app/llm/mistral_client.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import httpx
2
+ from typing import List
3
+ from app.llm.llm_client import LLMClient
4
+
5
+ OLLAMA_URL = "http://localhost:11434/api/generate"
6
+
7
+ class MistralClient(LLMClient):
8
+ async def generate(self, system_prompt: str, context: List[dict]) -> str:
9
+ # Flatten context into a string
10
+ formatted = "\n".join(f"{msg['role'].capitalize()}: {msg['content']}" for msg in context)
11
+ full_prompt = f"{system_prompt}\n\n{formatted}\n\nAssistant:"
12
+
13
+ payload = {
14
+ "model": "mistral",
15
+ "prompt": full_prompt,
16
+ "stream": False
17
+ }
18
+
19
+ try:
20
+ async with httpx.AsyncClient(timeout=60.0) as client:
21
+ response = await client.post(OLLAMA_URL, json=payload)
22
+ response.raise_for_status()
23
+ return response.json().get("response", "[No response]")
24
+ except httpx.HTTPError as e:
25
+ return f"[Error from Mistral: {str(e)}]"
multi_llm_chatbot_backend/app/main.py ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from app.api.routes import router
3
+
4
+ app = FastAPI(
5
+ title="Multi-LLM Chatbot Backend",
6
+ version="0.1"
7
+ )
8
+
9
+ # Include route definitions
10
+ app.include_router(router)
11
+
12
+ @app.get("/")
13
+ def root():
14
+ return {"message": "Backend is up and running"}
multi_llm_chatbot_backend/app/models/persona.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from app.llm.llm_client import LLMClient
2
+
3
+ class Persona:
4
+ def __init__(self, id: str, name: str, system_prompt: str, llm: LLMClient):
5
+ self.id = id
6
+ self.name = name
7
+ self.system_prompt = system_prompt
8
+ self.llm = llm
9
+
10
+ async def respond(self, context: list[dict]) -> str:
11
+ return await self.llm.generate(self.system_prompt, context)
multi_llm_chatbot_backend/app/tests/test_mistral.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+ url = "http://localhost:11434/api/generate"
4
+
5
+ payload = {
6
+ "model": "mistral",
7
+ "prompt": "You are a professor. Give me PhD advice.",
8
+ "stream": False
9
+ }
10
+
11
+ response = requests.post(url, json=payload)
12
+ print(response.status_code)
13
+ print(response.json())
multi_llm_chatbot_backend/requirements.txt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ httpx