middha commited on
Commit
5b6a148
Β·
verified Β·
1 Parent(s): 1dace6a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +38 -44
app.py CHANGED
@@ -1,14 +1,16 @@
1
- python
2
  import logging
3
  import os
4
  from logging.handlers import RotatingFileHandler
5
- from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, Response
 
 
 
 
6
  from flask_sqlalchemy import SQLAlchemy
7
  from flask_migrate import Migrate
8
  from sqlalchemy.exc import SQLAlchemyError
9
  from sqlalchemy import or_
10
  import pandas as pd
11
- import openai, sys
12
  from dotenv import load_dotenv
13
  from openai import OpenAI
14
  from datetime import datetime, timedelta
@@ -18,30 +20,27 @@ load_dotenv()
18
 
19
  # ─── Logging configuration ────────────────────────────────────────────────────
20
  os.makedirs("/tmp/logs", exist_ok=True)
21
-
22
  file_handler = RotatingFileHandler(
23
  "/tmp/logs/app.log", maxBytes=10_000_000, backupCount=5
24
  )
25
  file_handler.setFormatter(logging.Formatter(
26
  "[%(asctime)s] %(levelname)s in %(module)s: %(message)s"
27
  ))
28
-
29
  console_handler = logging.StreamHandler()
30
- console_handler.setFormatter(logging.Formatter(
31
- "[%(levelname)s] %(message)s"
32
- ))
33
 
34
  logging.basicConfig(level=logging.INFO, handlers=[console_handler, file_handler])
35
 
36
- # ─── Flask application setup ─────────────────────────────────────────────────
37
  app = Flask(__name__)
38
  app.logger.handlers = [console_handler, file_handler]
39
  app.logger.setLevel(logging.INFO)
40
 
41
- # ─── OpenAI client setup ─────────────────────────────────────────────────────
42
- openai.api_key = os.getenv("OPENAI_API_KEY")
43
- # or for the new v1 client:
44
- # client = OpenAI()
 
45
 
46
  # ─── Database configuration ───────────────────────────────────────────────────
47
  app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///jobs.db"
@@ -69,7 +68,6 @@ class Job(db.Model):
69
 
70
  # ─── Helpers ──────────────────────────────────────────────────────────────────
71
  def convert_excel_serial_dates():
72
- """Convert Excel serial dates in `date_applied` to ISO strings."""
73
  updated = False
74
  for job in Job.query.all():
75
  da = job.date_applied
@@ -86,14 +84,13 @@ def convert_excel_serial_dates():
86
  app.logger.info("Converted Excel serial dates to ISO strings")
87
 
88
  def generate_interview_plan(job_description: str) -> str:
89
- """Use OpenAI to generate an interview plan from the job description."""
90
  try:
91
- client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
92
  resp = client.chat.completions.create(
93
  model="gpt-4o-mini",
94
  messages=[
95
  {"role": "system", "content": "You are a helpful assistant."},
96
- {"role": "user", "content":
97
  f"Create an interview plan for the following job description. "
98
  f"Highlight key skills and requirements:\n{job_description}"
99
  },
@@ -101,11 +98,11 @@ def generate_interview_plan(job_description: str) -> str:
101
  max_tokens=150
102
  )
103
  return resp.choices[0].message.content.strip()
104
- except Exception as e:
105
- app.logger.error("Error generating interview plan", exc_info=True)
106
  return "Error generating interview plan. Please try again later."
107
 
108
- # ─── App Initialization ──────────────────────────────────────────────────────
109
  @app.before_first_request
110
  def initialize_database():
111
  db.create_all()
@@ -135,9 +132,9 @@ def jobs():
135
  db.session.add(new_job)
136
  db.session.commit()
137
  return redirect(url_for("jobs"))
138
- except SQLAlchemyError as e:
139
- app.logger.error("Error adding job", exc_info=True)
140
- flash(f"Error adding job: {e}")
141
  # GET
142
  search = request.args.get("search", "").strip()
143
  status_filter = request.args.get("status_filter", "").strip()
@@ -161,8 +158,8 @@ def jobs():
161
 
162
  jobs_list = query.all()
163
  counts = {
164
- "Applied": Job.query.filter_by(status="Applied").count(),
165
- "Rejected": Job.query.filter_by(status="Rejected").count(),
166
  "Interviewing": Job.query.filter_by(status="Interviewing").count()
167
  }
168
  return render_template(
@@ -191,9 +188,9 @@ def edit_job(job_id):
191
  job.job_description = request.form.get("job_description")
192
  db.session.commit()
193
  return redirect(url_for("jobs"))
194
- except SQLAlchemyError as e:
195
- app.logger.error("Error updating job", exc_info=True)
196
- flash(f"Error updating job: {e}")
197
  db.session.rollback()
198
  return render_template("jobs.html", jobs=Job.query.all(), edit_job=job)
199
 
@@ -203,9 +200,9 @@ def delete_job(job_id):
203
  try:
204
  db.session.delete(job)
205
  db.session.commit()
206
- except SQLAlchemyError as e:
207
- app.logger.error("Error deleting job", exc_info=True)
208
- flash(f"Error deleting job: {e}")
209
  db.session.rollback()
210
  return redirect(url_for("jobs"))
211
 
@@ -216,7 +213,7 @@ def api_chat():
216
  if not msg:
217
  return jsonify(response="Please type something!")
218
  try:
219
- client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
220
  resp = client.chat.completions.create(
221
  model="gpt-4o-mini",
222
  messages=[
@@ -226,9 +223,9 @@ def api_chat():
226
  max_tokens=150
227
  )
228
  return jsonify(response=resp.choices[0].message.content.strip())
229
- except Exception as e:
230
- app.logger.error("Chat API error", exc_info=True)
231
- return jsonify(response=f"Error: {e}")
232
 
233
  @app.route("/prepme/<int:job_id>")
234
  def prepme(job_id):
@@ -239,27 +236,25 @@ def prepme(job_id):
239
  from docx import Document
240
  doc = Document(resume_path)
241
  resume_content = "\n".join(p.text for p in doc.paragraphs)
242
- initial_context = f"Job Description:\n{job.job_description}\n\nResume:\n{resume_content}"
243
  try:
244
- client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
245
  resp = client.chat.completions.create(
246
  model="gpt-4o-mini",
247
  messages=[
248
  {"role": "system", "content": "You are a career coach."},
249
- {"role": "user", "content":
250
- f"Based on this context, help the user prepare:\n{initial_context}"
251
- },
252
  ],
253
  max_tokens=150
254
  )
255
  initial_response = resp.choices[0].message.content.strip()
256
- except Exception as e:
257
- app.logger.error("PrepMe error", exc_info=True)
258
  initial_response = "Error generating prep response."
259
  return render_template(
260
  "prepme.html",
261
  job=job,
262
- initial_context=initial_context,
263
  initial_response=initial_response
264
  )
265
 
@@ -302,4 +297,3 @@ def download_jobs():
302
  if __name__ == "__main__":
303
  port = int(os.environ.get("PORT", 5000))
304
  app.run(host="0.0.0.0", port=port, debug=False)
305
-
 
 
1
  import logging
2
  import os
3
  from logging.handlers import RotatingFileHandler
4
+
5
+ from flask import (
6
+ Flask, render_template, request, redirect,
7
+ url_for, flash, jsonify, Response
8
+ )
9
  from flask_sqlalchemy import SQLAlchemy
10
  from flask_migrate import Migrate
11
  from sqlalchemy.exc import SQLAlchemyError
12
  from sqlalchemy import or_
13
  import pandas as pd
 
14
  from dotenv import load_dotenv
15
  from openai import OpenAI
16
  from datetime import datetime, timedelta
 
20
 
21
  # ─── Logging configuration ────────────────────────────────────────────────────
22
  os.makedirs("/tmp/logs", exist_ok=True)
 
23
  file_handler = RotatingFileHandler(
24
  "/tmp/logs/app.log", maxBytes=10_000_000, backupCount=5
25
  )
26
  file_handler.setFormatter(logging.Formatter(
27
  "[%(asctime)s] %(levelname)s in %(module)s: %(message)s"
28
  ))
 
29
  console_handler = logging.StreamHandler()
30
+ console_handler.setFormatter(logging.Formatter("[%(levelname)s] %(message)s"))
 
 
31
 
32
  logging.basicConfig(level=logging.INFO, handlers=[console_handler, file_handler])
33
 
34
+ # ─── Flask setup ───────────────────────────────────────────────────────────────
35
  app = Flask(__name__)
36
  app.logger.handlers = [console_handler, file_handler]
37
  app.logger.setLevel(logging.INFO)
38
 
39
+ # ─── OpenAI client setup ──────────────────────────────────────────────────────
40
+ # client = OpenAI(api_key=os.getenv("OPENAI_API_KEY")) # if you prefer v1 client
41
+ OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
42
+ if not OPENAI_API_KEY:
43
+ app.logger.warning("OPENAI_API_KEY is not set in the environment")
44
 
45
  # ─── Database configuration ───────────────────────────────────────────────────
46
  app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///jobs.db"
 
68
 
69
  # ─── Helpers ──────────────────────────────────────────────────────────────────
70
  def convert_excel_serial_dates():
 
71
  updated = False
72
  for job in Job.query.all():
73
  da = job.date_applied
 
84
  app.logger.info("Converted Excel serial dates to ISO strings")
85
 
86
  def generate_interview_plan(job_description: str) -> str:
 
87
  try:
88
+ client = OpenAI(api_key=OPENAI_API_KEY)
89
  resp = client.chat.completions.create(
90
  model="gpt-4o-mini",
91
  messages=[
92
  {"role": "system", "content": "You are a helpful assistant."},
93
+ {"role": "user", "content":
94
  f"Create an interview plan for the following job description. "
95
  f"Highlight key skills and requirements:\n{job_description}"
96
  },
 
98
  max_tokens=150
99
  )
100
  return resp.choices[0].message.content.strip()
101
+ except Exception:
102
+ app.logger.exception("Error generating interview plan")
103
  return "Error generating interview plan. Please try again later."
104
 
105
+ # ─── Auto-initialize DB ────────────────────────────────────────────────────────
106
  @app.before_first_request
107
  def initialize_database():
108
  db.create_all()
 
132
  db.session.add(new_job)
133
  db.session.commit()
134
  return redirect(url_for("jobs"))
135
+ except SQLAlchemyError:
136
+ app.logger.exception("Error adding job")
137
+ flash("Error adding job. Check logs for details.")
138
  # GET
139
  search = request.args.get("search", "").strip()
140
  status_filter = request.args.get("status_filter", "").strip()
 
158
 
159
  jobs_list = query.all()
160
  counts = {
161
+ "Applied": Job.query.filter_by(status="Applied").count(),
162
+ "Rejected": Job.query.filter_by(status="Rejected").count(),
163
  "Interviewing": Job.query.filter_by(status="Interviewing").count()
164
  }
165
  return render_template(
 
188
  job.job_description = request.form.get("job_description")
189
  db.session.commit()
190
  return redirect(url_for("jobs"))
191
+ except SQLAlchemyError:
192
+ app.logger.exception("Error updating job")
193
+ flash("Error updating job. Check logs for details.")
194
  db.session.rollback()
195
  return render_template("jobs.html", jobs=Job.query.all(), edit_job=job)
196
 
 
200
  try:
201
  db.session.delete(job)
202
  db.session.commit()
203
+ except SQLAlchemyError:
204
+ app.logger.exception("Error deleting job")
205
+ flash("Error deleting job. Check logs for details.")
206
  db.session.rollback()
207
  return redirect(url_for("jobs"))
208
 
 
213
  if not msg:
214
  return jsonify(response="Please type something!")
215
  try:
216
+ client = OpenAI(api_key=OPENAI_API_KEY)
217
  resp = client.chat.completions.create(
218
  model="gpt-4o-mini",
219
  messages=[
 
223
  max_tokens=150
224
  )
225
  return jsonify(response=resp.choices[0].message.content.strip())
226
+ except Exception:
227
+ app.logger.exception("Chat API error")
228
+ return jsonify(response="Error during chat. See logs.")
229
 
230
  @app.route("/prepme/<int:job_id>")
231
  def prepme(job_id):
 
236
  from docx import Document
237
  doc = Document(resume_path)
238
  resume_content = "\n".join(p.text for p in doc.paragraphs)
239
+ context = f"Job Description:\n{job.job_description}\n\nResume:\n{resume_content}"
240
  try:
241
+ client = OpenAI(api_key=OPENAI_API_KEY)
242
  resp = client.chat.completions.create(
243
  model="gpt-4o-mini",
244
  messages=[
245
  {"role": "system", "content": "You are a career coach."},
246
+ {"role": "user", "content": context},
 
 
247
  ],
248
  max_tokens=150
249
  )
250
  initial_response = resp.choices[0].message.content.strip()
251
+ except Exception:
252
+ app.logger.exception("PrepMe error")
253
  initial_response = "Error generating prep response."
254
  return render_template(
255
  "prepme.html",
256
  job=job,
257
+ initial_context=context,
258
  initial_response=initial_response
259
  )
260
 
 
297
  if __name__ == "__main__":
298
  port = int(os.environ.get("PORT", 5000))
299
  app.run(host="0.0.0.0", port=port, debug=False)