Spaces:
Running
Running
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
llm=llm_client
|
| 125 |
),
|
| 126 |
Persona(
|
| 127 |
id="theorist",
|
| 128 |
name="Theorist Advisor",
|
| 129 |
-
system_prompt="You are Dr. Theorist
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 130 |
llm=llm_client
|
| 131 |
),
|
| 132 |
Persona(
|
| 133 |
id="pragmatist",
|
| 134 |
name="Pragmatist Advisor",
|
| 135 |
-
system_prompt="You are
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.")
|