Sohan Kshirsagar commited on
Commit
409ad9f
·
1 Parent(s): 87fd07d

document upload support

Browse files
multi_llm_chatbot_backend/app/api/routes.py CHANGED
@@ -8,6 +8,8 @@ from app.core.orchestrator import ChatOrchestrator
8
  from app.core.seamless_orchestrator import SeamlessOrchestrator
9
  from pydantic import BaseModel
10
  from typing import Optional, List
 
 
11
 
12
  router = APIRouter()
13
 
@@ -120,19 +122,33 @@ def create_default_personas(llm_client: LLMClient):
120
  Persona(
121
  id="methodist",
122
  name="Methodist Advisor",
123
- system_prompt="You are Dr. Methodist, a structured PhD advisor. Give brief, organized advice in 2-3 clear sentences. Focus on systematic approaches and planning.",
 
 
 
 
 
124
  llm=llm_client
125
  ),
126
  Persona(
127
  id="theorist",
128
  name="Theorist Advisor",
129
- system_prompt="You are Dr. Theorist, a philosophical PhD advisor. Give brief, thoughtful insights in 2-3 sentences. Focus on concepts, frameworks, and deeper understanding.",
 
 
 
 
 
130
  llm=llm_client
131
  ),
132
  Persona(
133
  id="pragmatist",
134
  name="Pragmatist Advisor",
135
- system_prompt="You are Dr. Pragmatist, a practical PhD advisor. Give brief, actionable advice in 2-3 sentences. Focus on concrete steps and real-world solutions.",
 
 
 
 
136
  llm=llm_client
137
  )
138
  ]
@@ -393,6 +409,34 @@ async def get_current_model():
393
  "provider": current_provider
394
  }
395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
396
  # Debug endpoint
397
  @router.get("/debug/personas")
398
  async def debug_personas():
 
8
  from app.core.seamless_orchestrator import SeamlessOrchestrator
9
  from pydantic import BaseModel
10
  from typing import Optional, List
11
+ from fastapi import UploadFile, File
12
+ from app.utils.document_extractor import extract_text_from_file
13
 
14
  router = APIRouter()
15
 
 
122
  Persona(
123
  id="methodist",
124
  name="Methodist Advisor",
125
+ system_prompt="You are Dr. Methodist a meticulous, discipline-neutral advisor who specializes in research design, methodology, and validity." \
126
+ "Your primary concern is whether the student's research plan is methodologically sound, feasible, and aligned with their stated research question." \
127
+ "You value clarity, precision, and logical alignment between claims, methods, and outcomes. You often use language like “operationalize,”" \
128
+ "“sampling frame,” “construct validity,” and “replication.” You frequently ask students to explain why a method is appropriate and whether " \
129
+ "alternative designs might be more rigorous or parsimonious. You are not rude or dismissive, but you don’t sugarcoat weak designs. You believe" \
130
+ " good methods are teachable and worth defending. Always explain your reasoning and, if appropriate, recommend ways to tighten or clarify the student’s approach.",
131
  llm=llm_client
132
  ),
133
  Persona(
134
  id="theorist",
135
  name="Theorist Advisor",
136
+ system_prompt="You are Dr. Theorist an intellectually deep advisor who focuses on conceptual clarity, theoretical framing, and epistemological depth. You " \
137
+ "are most helpful when a student needs to articulate, refine, or rethink the theoretical foundations of their work. You often ask questions like " \
138
+ "“What assumptions underlie this framework?” or “How does this relate to tradition X or thinker Y?” You encourage students to think about ontology, " \
139
+ "positionality, and the meaning of key terms in their research. You reference theories, concepts, and debates — especially from the humanities and " \
140
+ "social sciences — to help students sharpen their ideas. Your tone is thoughtful and reflective. You don’t rush to judgment but probe until the student's" \
141
+ " conceptual scaffolding is robust. Avoid vague praise or technical critique — your role is to illuminate the deeper structure of ideas.",
142
  llm=llm_client
143
  ),
144
  Persona(
145
  id="pragmatist",
146
  name="Pragmatist Advisor",
147
+ system_prompt="You are The Pragmatist an action-focused advisor who helps students move forward when they feel overwhelmed, stuck, or overthinking. You " \
148
+ "prioritize clarity over perfection, progress over polish, and “done” over ideal. You frequently say things like “Let’s break this down” or “What’s one thing" \
149
+ " you can do today?” You are warm, practical, and motivational. You don’t dwell on critique unless it helps unblock the student. You are especially helpful during" \
150
+ " early drafts, decision paralysis, or writer’s block. Your suggestions should be immediately actionable, even if they’re not perfect. Always focus on the next step,"
151
+ " and help reduce cognitive load wherever possible.",
152
  llm=llm_client
153
  )
154
  ]
 
409
  "provider": current_provider
410
  }
411
 
412
+ @router.post("/upload-document")
413
+ async def upload_document(file: UploadFile = File(...)):
414
+ if file.content_type not in [
415
+ "application/pdf",
416
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
417
+ "text/plain"
418
+ ]:
419
+ raise HTTPException(status_code=400, detail="Unsupported file type.")
420
+
421
+ try:
422
+ # Read file content into memory
423
+ contents = await file.read()
424
+
425
+ # Now pass raw contents and file type to extractor
426
+ content = extract_text_from_file(contents, file.content_type)
427
+
428
+ if not content.strip():
429
+ raise HTTPException(status_code=400, detail="Document is empty or unreadable.")
430
+
431
+ session_context.append("user", f"[Uploaded Document Content]\n{content.strip()}")
432
+
433
+ return {"message": "Document uploaded and added to context successfully."}
434
+
435
+ except Exception as e:
436
+ raise HTTPException(status_code=500, detail=f"Error processing document: {str(e)}")
437
+
438
+
439
+
440
  # Debug endpoint
441
  @router.get("/debug/personas")
442
  async def debug_personas():
multi_llm_chatbot_backend/app/utils/document_extractor.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tempfile
2
+ import docx2txt
3
+ import PyPDF2
4
+ from io import BytesIO
5
+
6
+ def extract_text_from_file(file_bytes: bytes, content_type: str) -> str:
7
+ if content_type == "application/pdf":
8
+ reader = PyPDF2.PdfReader(BytesIO(file_bytes))
9
+ return "\n".join(page.extract_text() for page in reader.pages if page.extract_text())
10
+
11
+ elif content_type == "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
12
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".docx") as tmp:
13
+ tmp.write(file_bytes)
14
+ tmp_path = tmp.name
15
+ try:
16
+ return docx2txt.process(tmp_path)
17
+ finally:
18
+ os.unlink(tmp_path) # Clean up temp file
19
+
20
+ elif content_type == "text/plain":
21
+ return file_bytes.decode("utf-8")
22
+
23
+ else:
24
+ raise ValueError("Unsupported file type.")