cxumol commited on
Commit
ccc2190
1 Parent(s): e82f42a
Files changed (3) hide show
  1. app.py +45 -11
  2. taskAI.py +1 -1
  3. taskNonAI.py +3 -1
app.py CHANGED
@@ -36,7 +36,15 @@ def init():
36
  ## Config Functions
37
 
38
 
39
- def set_same_cheap_strong(set_same: bool, cheap_base, cheap_key, cheap_model, strong_base, strong_key, strong_model):
 
 
 
 
 
 
 
 
40
  # setup_zone = gr.Accordion("AI setup (OpenAI-compatible LLM API)", open=True)
41
  if set_same:
42
  return (
@@ -114,10 +122,11 @@ def finalize_letter_txt(api_base, api_key, api_model, debug_CoT):
114
  for response in taskAI.purify_letter(full_text=debug_CoT):
115
  result += response.delta
116
  yield result
117
-
118
 
119
 
120
- def finalize_letter_pdf(api_base, api_key, api_model, jd, cv, cover_letter_text, is_debug):
 
 
121
  cheapAPI = {"base": api_base, "key": api_key, "model": api_model}
122
  taskAI = TaskAI(cheapAPI, temperature=0.1, max_tokens=100)
123
  meta_data = next(taskAI.get_jobapp_meta(JD=jd, CV=cv))
@@ -135,14 +144,23 @@ def finalize_letter_pdf(api_base, api_key, api_model, jd, cv, cover_letter_text,
135
 
136
  with gr.Blocks(
137
  title=DEMO_TITLE,
138
- theme=gr.themes.Soft(primary_hue="sky", secondary_hue="emerald", neutral_hue="stone"),
 
 
139
  ) as app:
140
  intro = f"""# {DEMO_TITLE}
141
- > You provide job description and résumé. I write Cover letter for you!
142
- Before you use, please fisrt setup API for 2 AI agents': Cheap AI and Strong AI.
143
  """
144
  gr.Markdown(intro)
145
-
 
 
 
 
 
 
 
146
  with gr.Row():
147
  with gr.Column(scale=1):
148
  with gr.Accordion(
@@ -151,7 +169,7 @@ with gr.Blocks(
151
  is_debug = gr.Checkbox(label="Debug Mode", value=IS_DEBUG)
152
 
153
  gr.Markdown(
154
- "**Cheap AI**, an honest format converter and refiner, extracts essential info from job description and résumé, to reduce subsequent cost on Strong AI."
155
  )
156
  with gr.Group():
157
  cheap_base = gr.Textbox(value=CHEAP_API_BASE, label="API Base")
@@ -160,7 +178,7 @@ with gr.Blocks(
160
  )
161
  cheap_model = gr.Textbox(value=CHEAP_MODEL, label="Model ID")
162
  gr.Markdown(
163
- "---\n**Strong AI**, a thoughtful wordsmith, generates perfect cover letters to make both you and recruiters happy."
164
  )
165
  is_same_cheap_strong = gr.Checkbox(
166
  label="the same as Cheap AI", value=False, container=False
@@ -211,13 +229,29 @@ with gr.Blocks(
211
 
212
  is_same_cheap_strong.change(
213
  fn=set_same_cheap_strong,
214
- inputs=[is_same_cheap_strong, cheap_base, cheap_key, cheap_model, strong_base, strong_key, strong_model],
 
 
 
 
 
 
 
 
215
  outputs=[strong_base, strong_key, strong_model],
216
  )
217
 
218
  infer_btn.click(
219
  fn=set_same_cheap_strong,
220
- inputs=[is_same_cheap_strong, cheap_base, cheap_key, cheap_model, strong_base, strong_key, strong_model],
 
 
 
 
 
 
 
 
221
  outputs=[strong_base, strong_key, strong_model],
222
  ).success(
223
  fn=prepare_input, inputs=[jd_info, cv_file, cv_text], outputs=[jd_info, cv_text]
 
36
  ## Config Functions
37
 
38
 
39
+ def set_same_cheap_strong(
40
+ set_same: bool,
41
+ cheap_base,
42
+ cheap_key,
43
+ cheap_model,
44
+ strong_base,
45
+ strong_key,
46
+ strong_model,
47
+ ):
48
  # setup_zone = gr.Accordion("AI setup (OpenAI-compatible LLM API)", open=True)
49
  if set_same:
50
  return (
 
122
  for response in taskAI.purify_letter(full_text=debug_CoT):
123
  result += response.delta
124
  yield result
 
125
 
126
 
127
+ def finalize_letter_pdf(
128
+ api_base, api_key, api_model, jd, cv, cover_letter_text, is_debug
129
+ ):
130
  cheapAPI = {"base": api_base, "key": api_key, "model": api_model}
131
  taskAI = TaskAI(cheapAPI, temperature=0.1, max_tokens=100)
132
  meta_data = next(taskAI.get_jobapp_meta(JD=jd, CV=cv))
 
144
 
145
  with gr.Blocks(
146
  title=DEMO_TITLE,
147
+ theme=gr.themes.Soft(
148
+ primary_hue="sky", secondary_hue="emerald", neutral_hue="stone"
149
+ ),
150
  ) as app:
151
  intro = f"""# {DEMO_TITLE}
152
+ > You provide job description and résumé, and I write Cover letter for you!
153
+ Before you use, please fisrt setup API for 2 AI agents': **CheapAI** and StrongAI.
154
  """
155
  gr.Markdown(intro)
156
+ with gr.Accordion("User Guide", open=False):
157
+ guide = gr.Markdown("""## Setup
158
+ `API Key`: If you have no idea, go to https://beta.openai.com/account/api-keys
159
+
160
+ `Model ID` to choose:
161
+ - **CheapAI**: `gpt-3.5-turbo-*` should be fine if OpenAI won't make them lazier and dumber. `Mistral-7B-Instruct-v0.1` works well, but `gemma-7b-it` doesn't, because gemma can't understand instructions properly in this case.
162
+ - **StrongAI**: Models with small context window size like won't work, such as `gpt-3.5-turbo-0613` or perhaps `gpt-4-0613`. `Mistral-7B-Instruct-v0.1` can do the job.
163
+ """)
164
  with gr.Row():
165
  with gr.Column(scale=1):
166
  with gr.Accordion(
 
169
  is_debug = gr.Checkbox(label="Debug Mode", value=IS_DEBUG)
170
 
171
  gr.Markdown(
172
+ "**CheapAI**, an honest format converter and refiner, extracts essential info from job description and résumé, to reduce subsequent cost on Strong AI."
173
  )
174
  with gr.Group():
175
  cheap_base = gr.Textbox(value=CHEAP_API_BASE, label="API Base")
 
178
  )
179
  cheap_model = gr.Textbox(value=CHEAP_MODEL, label="Model ID")
180
  gr.Markdown(
181
+ "---\n**StrongAI**, a thoughtful wordsmith, generates perfect cover letters to make both you and recruiters happy."
182
  )
183
  is_same_cheap_strong = gr.Checkbox(
184
  label="the same as Cheap AI", value=False, container=False
 
229
 
230
  is_same_cheap_strong.change(
231
  fn=set_same_cheap_strong,
232
+ inputs=[
233
+ is_same_cheap_strong,
234
+ cheap_base,
235
+ cheap_key,
236
+ cheap_model,
237
+ strong_base,
238
+ strong_key,
239
+ strong_model,
240
+ ],
241
  outputs=[strong_base, strong_key, strong_model],
242
  )
243
 
244
  infer_btn.click(
245
  fn=set_same_cheap_strong,
246
+ inputs=[
247
+ is_same_cheap_strong,
248
+ cheap_base,
249
+ cheap_key,
250
+ cheap_model,
251
+ strong_base,
252
+ strong_key,
253
+ strong_model,
254
+ ],
255
  outputs=[strong_base, strong_key, strong_model],
256
  ).success(
257
  fn=prepare_input, inputs=[jd_info, cv_file, cv_text], outputs=[jd_info, cv_text]
taskAI.py CHANGED
@@ -68,6 +68,7 @@ Before officially write the letter, think step by step. First, list what makes a
68
  ## tasks
69
  class TaskAI(OpenAILike):
70
  is_debug = False
 
71
  def __init__(self, api: dict[str, str], is_debug=False, **kwargs):
72
  log = logger.info
73
 
@@ -86,7 +87,6 @@ class TaskAI(OpenAILike):
86
  return window_size
87
 
88
  checkAPI(api_base=api["base"], api_key=api["key"])
89
-
90
 
91
  super().__init__(
92
  api_base=api["base"],
 
68
  ## tasks
69
  class TaskAI(OpenAILike):
70
  is_debug = False
71
+
72
  def __init__(self, api: dict[str, str], is_debug=False, **kwargs):
73
  log = logger.info
74
 
 
87
  return window_size
88
 
89
  checkAPI(api_base=api["base"], api_key=api["key"])
 
90
 
91
  super().__init__(
92
  api_base=api["base"],
taskNonAI.py CHANGED
@@ -54,12 +54,14 @@ def _date() -> str:
54
  def _typst_escape(s) -> str:
55
  return str(s).replace("@", "\@").replace("#", "\#")
56
 
 
57
  def _ensure_no_signature_in_body(cover_letter_body: str) -> str:
58
  if not cover_letter_body.strip().endswith(","):
59
  # remove last line
60
  cover_letter_body = "\n".join(cover_letter_body.split("\n")[:-1])
61
  return cover_letter_body
62
 
 
63
  def compile_pdf(
64
  context: dict, tmpl_path: str, output_path="/tmp/cover_letter.pdf", is_debug=False
65
  ) -> list[str]:
@@ -69,7 +71,7 @@ def compile_pdf(
69
  tmpl = Template(f.read())
70
  context = {k: _typst_escape(v) for k, v in context.items()}
71
  context.update({"date_string": _date()})
72
- context["letter_body"]=_ensure_no_signature_in_body(context["letter_body"])
73
 
74
  letter_typ = tmpl.safe_substitute(context)
75
  with open(letter_src_filepath, "w", encoding="utf8") as f:
 
54
  def _typst_escape(s) -> str:
55
  return str(s).replace("@", "\@").replace("#", "\#")
56
 
57
+
58
  def _ensure_no_signature_in_body(cover_letter_body: str) -> str:
59
  if not cover_letter_body.strip().endswith(","):
60
  # remove last line
61
  cover_letter_body = "\n".join(cover_letter_body.split("\n")[:-1])
62
  return cover_letter_body
63
 
64
+
65
  def compile_pdf(
66
  context: dict, tmpl_path: str, output_path="/tmp/cover_letter.pdf", is_debug=False
67
  ) -> list[str]:
 
71
  tmpl = Template(f.read())
72
  context = {k: _typst_escape(v) for k, v in context.items()}
73
  context.update({"date_string": _date()})
74
+ context["letter_body"] = _ensure_no_signature_in_body(context["letter_body"])
75
 
76
  letter_typ = tmpl.safe_substitute(context)
77
  with open(letter_src_filepath, "w", encoding="utf8") as f: