ankban commited on
Commit
4cbb464
·
verified ·
1 Parent(s): 1219274

Update file_utils.py

Browse files
Files changed (1) hide show
  1. file_utils.py +43 -35
file_utils.py CHANGED
@@ -15,7 +15,7 @@ SQLModel.metadata.create_all(engine)
15
  openai_api_key = os.getenv("OPENAI_API_KEY")
16
  client = OpenAI(api_key=openai_api_key)
17
 
18
- # === DB Table for Study Guides ===
19
  class StudyGuideEntry(SQLModel, table=True):
20
  id: Optional[int] = Field(default=None, primary_key=True)
21
  user: str
@@ -23,7 +23,35 @@ class StudyGuideEntry(SQLModel, table=True):
23
  guide: str
24
  timestamp: str
25
 
26
- # === DB Utilities ===
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  def save_study_guide(user, filename, guide):
28
  session = Session(engine)
29
  entry = StudyGuideEntry(
@@ -43,31 +71,14 @@ def fetch_study_guides(user):
43
  session.close()
44
  return results
45
 
46
- # === GPT Utility ===
47
  def call_llm(prompt=None, system_message="You are a helpful assistant.", messages=None):
48
- """
49
- Call GPT-4 with either a single prompt or full message history.
50
- Handles token limits and returns a single string response.
51
-
52
- Args:
53
- prompt (str): Optional one-turn prompt.
54
- system_message (str): Optional system message.
55
- messages (list): Optional list of chat messages (for multi-turn chat).
56
-
57
- Returns:
58
- str: The assistant's reply.
59
- """
60
- max_tokens = 8192
61
- max_safe_chars = 28000 # Roughly ~7000 tokens
62
-
63
  if messages:
64
- # Optional: truncate text-heavy messages
65
  for msg in messages:
66
  if len(msg["content"]) > max_safe_chars:
67
  msg["content"] = msg["content"][:max_safe_chars] + "\n\n[Truncated due to token limit]"
68
-
69
  else:
70
- # One-shot prompt mode
71
  if prompt and len(prompt) > max_safe_chars:
72
  prompt = prompt[:max_safe_chars] + "\n\n[Truncated due to token limit]"
73
  messages = [
@@ -80,48 +91,45 @@ def call_llm(prompt=None, system_message="You are a helpful assistant.", message
80
  messages=messages,
81
  temperature=0.7
82
  )
83
-
84
  return response.choices[0].message.content
85
 
86
-
87
  # === File Parsing ===
88
  def extract_text_from_file(file):
89
  ext = os.path.splitext(file.name)[1].lower()
90
-
91
  if ext == ".pdf":
92
  with fitz.open(file.name) as doc:
93
  return "\n".join([page.get_text() for page in doc])
94
-
95
  elif ext in [".txt", ".md"]:
96
  return file.read().decode("utf-8")
97
-
98
  elif ext == ".pptx":
99
  prs = Presentation(file.name)
100
  return "\n".join([
101
  shape.text for slide in prs.slides for shape in slide.shapes if hasattr(shape, "text")
102
  ])
103
-
104
  else:
105
  return "Unsupported file type."
106
 
107
  # === GPT-Based Generators ===
108
-
109
  def generate_summary(text):
110
  prompt = f"Summarize the following document in 5–7 bullet points:\n\n{text}"
111
- return call_llm(prompt)
112
 
113
  def generate_flashcards(text):
114
- prompt = f"Generate 5 flashcards based on this document. Each flashcard should follow this format:\nQ: ...\nA: ...\n\n{text}"
115
- return call_llm(prompt)
 
 
 
 
116
 
117
  def generate_quiz(text):
118
  prompt = (
119
- "Generate 5 multiple choice questions based on the document below. "
120
- "Return the result as a JSON array where each item has:\n"
121
  "- question (string)\n- options (list of strings)\n- answer (correct option string)\n\n"
122
  f"{text}"
123
  )
124
- response = call_llm(prompt)
125
  try:
126
  return json.loads(response)
127
  except:
@@ -129,4 +137,4 @@ def generate_quiz(text):
129
 
130
  def answer_question(text, question):
131
  prompt = f"Using only the document below, answer this question:\n\nDocument:\n{text}\n\nQuestion:\n{question}"
132
- return call_llm(prompt)
 
15
  openai_api_key = os.getenv("OPENAI_API_KEY")
16
  client = OpenAI(api_key=openai_api_key)
17
 
18
+ # === DB Tables ===
19
  class StudyGuideEntry(SQLModel, table=True):
20
  id: Optional[int] = Field(default=None, primary_key=True)
21
  user: str
 
23
  guide: str
24
  timestamp: str
25
 
26
+ class UserFileEntry(SQLModel, table=True):
27
+ id: Optional[int] = Field(default=None, primary_key=True)
28
+ user: str
29
+ filename: str
30
+ file_path: str
31
+ timestamp: str
32
+
33
+ SQLModel.metadata.create_all(engine)
34
+
35
+ # === File Persistence ===
36
+ def save_user_file(user, filename, file_path):
37
+ session = Session(engine)
38
+ entry = UserFileEntry(
39
+ user=user,
40
+ filename=filename,
41
+ file_path=file_path,
42
+ timestamp=datetime.now().strftime("%Y-%m-%d %H:%M")
43
+ )
44
+ session.add(entry)
45
+ session.commit()
46
+ session.close()
47
+
48
+ def fetch_user_files(user):
49
+ session = Session(engine)
50
+ statement = select(UserFileEntry).where(UserFileEntry.user == user)
51
+ results = session.exec(statement).all()
52
+ session.close()
53
+ return results
54
+
55
  def save_study_guide(user, filename, guide):
56
  session = Session(engine)
57
  entry = StudyGuideEntry(
 
71
  session.close()
72
  return results
73
 
74
+ # === LLM Core ===
75
  def call_llm(prompt=None, system_message="You are a helpful assistant.", messages=None):
76
+ max_safe_chars = 28000
 
 
 
 
 
 
 
 
 
 
 
 
 
 
77
  if messages:
 
78
  for msg in messages:
79
  if len(msg["content"]) > max_safe_chars:
80
  msg["content"] = msg["content"][:max_safe_chars] + "\n\n[Truncated due to token limit]"
 
81
  else:
 
82
  if prompt and len(prompt) > max_safe_chars:
83
  prompt = prompt[:max_safe_chars] + "\n\n[Truncated due to token limit]"
84
  messages = [
 
91
  messages=messages,
92
  temperature=0.7
93
  )
 
94
  return response.choices[0].message.content
95
 
 
96
  # === File Parsing ===
97
  def extract_text_from_file(file):
98
  ext = os.path.splitext(file.name)[1].lower()
 
99
  if ext == ".pdf":
100
  with fitz.open(file.name) as doc:
101
  return "\n".join([page.get_text() for page in doc])
 
102
  elif ext in [".txt", ".md"]:
103
  return file.read().decode("utf-8")
 
104
  elif ext == ".pptx":
105
  prs = Presentation(file.name)
106
  return "\n".join([
107
  shape.text for slide in prs.slides for shape in slide.shapes if hasattr(shape, "text")
108
  ])
 
109
  else:
110
  return "Unsupported file type."
111
 
112
  # === GPT-Based Generators ===
 
113
  def generate_summary(text):
114
  prompt = f"Summarize the following document in 5–7 bullet points:\n\n{text}"
115
+ return call_llm(prompt=prompt)
116
 
117
  def generate_flashcards(text):
118
+ prompt = (
119
+ "Generate 5 flashcards based on the document below.\n"
120
+ "Each flashcard should follow this format:\nQ: <question>\nA: <answer>\n\n"
121
+ f"{text}"
122
+ )
123
+ return call_llm(prompt=prompt)
124
 
125
  def generate_quiz(text):
126
  prompt = (
127
+ "Generate 5 multiple choice questions from the document below. "
128
+ "Return a JSON array where each item has:\n"
129
  "- question (string)\n- options (list of strings)\n- answer (correct option string)\n\n"
130
  f"{text}"
131
  )
132
+ response = call_llm(prompt=prompt)
133
  try:
134
  return json.loads(response)
135
  except:
 
137
 
138
  def answer_question(text, question):
139
  prompt = f"Using only the document below, answer this question:\n\nDocument:\n{text}\n\nQuestion:\n{question}"
140
+ return call_llm(prompt=prompt)