File size: 5,021 Bytes
bdda033 36fe359 bdda033 8e9e651 bdda033 5a56bb7 4cbb464 bdda033 5a56bb7 4cbb464 fa903e0 4cbb464 bdda033 5a56bb7 bdda033 5a56bb7 fa903e0 4cbb464 9be22f3 4cbb464 9be22f3 bdda033 9be22f3 bdda033 4cbb464 bdda033 4cbb464 bdda033 4cbb464 bdda033 4cbb464 bdda033 4cbb464 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | from sqlmodel import SQLModel, Field, create_engine, Session, select
from datetime import datetime
from typing import Optional
import os
import json
from pptx import Presentation
import fitz # PyMuPDF
from openai import OpenAI
# === Setup ===
db_path = "/tmp/chatter_sessions.db"
engine = create_engine(f"sqlite:///{db_path}")
SQLModel.metadata.create_all(engine)
openai_api_key = os.getenv("OPENAI_API_KEY")
client = OpenAI(api_key=openai_api_key)
# === DB Tables ===
class StudyGuideEntry(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
user: str
filename: str
guide: str
timestamp: str
class UserFileEntry(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
user: str
filename: str
file_path: str
timestamp: str
class UserProfile(SQLModel, table=True):
id: Optional[int] = Field(default=None, primary_key=True)
nickname: str
timestamp: str
SQLModel.metadata.create_all(engine)
# === File Persistence ===
def save_user_file(user, filename, file_path):
session = Session(engine)
entry = UserFileEntry(
user=user,
filename=filename,
file_path=file_path,
timestamp=datetime.now().strftime("%Y-%m-%d %H:%M")
)
session.add(entry)
session.commit()
session.close()
def fetch_user_files(user):
session = Session(engine)
statement = select(UserFileEntry).where(UserFileEntry.user == user)
results = session.exec(statement).all()
session.close()
return results
def save_study_guide(user, filename, guide):
session = Session(engine)
entry = StudyGuideEntry(
user=user,
filename=filename,
guide=guide,
timestamp=datetime.now().strftime("%Y-%m-%d %H:%M")
)
session.add(entry)
session.commit()
session.close()
def fetch_study_guides(user):
session = Session(engine)
statement = select(StudyGuideEntry).where(StudyGuideEntry.user == user)
results = session.exec(statement).all()
session.close()
return results
def save_nickname_to_db(nickname):
session = Session(engine)
existing = session.exec(select(UserProfile).where(UserProfile.nickname == nickname)).first()
if not existing:
entry = UserProfile(nickname=nickname, timestamp=datetime.now().strftime("%Y-%m-%d %H:%M"))
session.add(entry)
session.commit()
session.close()
def load_latest_nickname():
session = Session(engine)
result = session.exec(select(UserProfile).order_by(UserProfile.id.desc())).first()
session.close()
return result.nickname if result else ""
# === LLM Core ===
def call_llm(prompt=None, system_message="You are a helpful assistant.", messages=None):
max_safe_chars = 28000
if messages:
for msg in messages:
if len(msg["content"]) > max_safe_chars:
msg["content"] = msg["content"][:max_safe_chars] + "\n\n[Truncated due to token limit]"
else:
if prompt and len(prompt) > max_safe_chars:
prompt = prompt[:max_safe_chars] + "\n\n[Truncated due to token limit]"
messages = [
{"role": "system", "content": system_message},
{"role": "user", "content": prompt}
]
response = client.chat.completions.create(
model="gpt-4",
messages=messages,
temperature=0.7
)
return response.choices[0].message.content
# === File Parsing ===
def extract_text_from_file(file):
ext = os.path.splitext(file.name)[1].lower()
if ext == ".pdf":
with fitz.open(file.name) as doc:
return "\n".join([page.get_text() for page in doc])
elif ext in [".txt", ".md"]:
return file.read().decode("utf-8")
elif ext == ".pptx":
prs = Presentation(file.name)
return "\n".join([
shape.text for slide in prs.slides for shape in slide.shapes if hasattr(shape, "text")
])
else:
return "Unsupported file type."
# === GPT-Based Generators ===
def generate_summary(text):
prompt = f"Summarize the following document in 5–7 bullet points:\n\n{text}"
return call_llm(prompt=prompt)
def generate_flashcards(text):
prompt = (
"Generate 5 flashcards based on the document below.\n"
"Each flashcard should follow this format:\nQ: <question>\nA: <answer>\n\n"
f"{text}"
)
return call_llm(prompt=prompt)
def generate_quiz(text):
prompt = (
"Generate 5 multiple choice questions from the document below. "
"Return a JSON array where each item has:\n"
"- question (string)\n- options (list of strings)\n- answer (correct option string)\n\n"
f"{text}"
)
response = call_llm(prompt=prompt)
try:
return json.loads(response)
except:
return []
def answer_question(text, question):
prompt = f"Using only the document below, answer this question:\n\nDocument:\n{text}\n\nQuestion:\n{question}"
return call_llm(prompt=prompt)
|