Corin1998 commited on
Commit
e88de2a
·
verified ·
1 Parent(s): d470e83

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +25 -15
app.py CHANGED
@@ -37,7 +37,7 @@ def process_resumes(filepaths, candidate_id: str, additional_notes: str = ""):
37
  fname = os.path.basename(p)
38
  filetype = detect_filetype(fname, raw_bytes)
39
 
40
- # 1) テキスト抽出:画像/PDFはOpenAI Vision OCR、docx/txtは生文面+OpenAI整形
41
  if filetype in {"pdf", "image"}:
42
  text = extract_text_with_openai(raw_bytes, filename=fname, filetype=filetype)
43
  else:
@@ -46,7 +46,7 @@ def process_resumes(filepaths, candidate_id: str, additional_notes: str = ""):
46
 
47
  raw_texts.append({"filename": fname, "text": text})
48
 
49
- # 2) OpenAIでセクション構造化 → ルール正規化
50
  structured = structure_with_openai(text)
51
  normalized = normalize_resume({
52
  "work_experience": structured.get("work_experience_raw", ""),
@@ -61,10 +61,10 @@ def process_resumes(filepaths, candidate_id: str, additional_notes: str = ""):
61
  "normalized": normalized,
62
  })
63
 
64
- # 3) 統合(複数ファイル→1候補者)
65
  merged = merge_normalized_records([r["normalized"] for r in partial_records])
66
 
67
- # 4) スキル抽出
68
  merged_text = "\n\n".join([r["text"] for r in partial_records])
69
  skills = extract_skills(merged_text, {
70
  "work_experience": merged.get("raw_sections", {}).get("work_experience", ""),
@@ -73,17 +73,17 @@ def process_resumes(filepaths, candidate_id: str, additional_notes: str = ""):
73
  "skills": ", ".join(merged.get("skills", [])),
74
  })
75
 
76
- # 5) 匿名化
77
  anonymized_text, anon_map = anonymize_text(merged_text)
78
  anon_pdf_bytes = render_anonymized_pdf(anonymized_text)
79
 
80
- # 6) 品質スコア
81
  score = compute_quality_score(merged_text, merged)
82
 
83
- # 7) 要約(300/100/1文)
84
  summaries = summarize_with_openai(merged_text)
85
 
86
- # 8) 構造化出力
87
  result_json = {
88
  "candidate_id": candidate_id or hashlib.sha256(merged_text.encode("utf-8")).hexdigest()[:16],
89
  "files": [os.path.basename(p) for p in filepaths],
@@ -95,7 +95,7 @@ def process_resumes(filepaths, candidate_id: str, additional_notes: str = ""):
95
  "notes": additional_notes,
96
  }
97
 
98
- # 9) HF Datasets 保存
99
  dataset_repo = os.environ.get("DATASET_REPO")
100
  commit_info = None
101
  if dataset_repo:
@@ -111,7 +111,7 @@ def process_resumes(filepaths, candidate_id: str, additional_notes: str = ""):
111
 
112
  anon_pdf = (result_json["candidate_id"] + ".anon.pdf", anon_pdf_bytes)
113
 
114
- # 出力はすべて文字列/ファイルに統一(GradioのAPI情報生成で安全)
115
  return (
116
  json.dumps(result_json, ensure_ascii=False, indent=2),
117
  json.dumps(skills, ensure_ascii=False, indent=2),
@@ -128,11 +128,12 @@ with gr.Blocks(title=APP_TITLE) as demo:
128
  gr.Markdown(f"# {APP_TITLE}\n複数ファイルを統合→OpenAIで読み込み/構造化/要約→匿名化→Datasets保存")
129
 
130
  with gr.Row():
 
131
  in_files = gr.Files(
132
  label="レジュメ類 (PDF/画像/Word/テキスト) 複数可",
133
  file_count="multiple",
134
  file_types=[".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".bmp", ".docx", ".txt"],
135
- type="filepath", # 重要:filepath に統一
136
  )
137
  candidate_id = gr.Textbox(label="候補者ID(任意。未入力なら自動生成)")
138
  notes = gr.Textbox(label="補足メモ(任意)", lines=3)
@@ -143,6 +144,7 @@ with gr.Blocks(title=APP_TITLE) as demo:
143
  out_json = gr.Code(label="統合出力 (JSON)")
144
 
145
  with gr.Tab("抽出スキル"):
 
146
  out_skills = gr.Code(label="スキル一覧 (JSON)")
147
 
148
  with gr.Tab("品質スコア"):
@@ -167,7 +169,15 @@ with gr.Blocks(title=APP_TITLE) as demo:
167
 
168
 
169
  if __name__ == "__main__":
170
- # Spaces でもローカルでも OK
171
- demo.launch(server_name=os.getenv("GRADIO_SERVER_NAME", "0.0.0.0"),
172
- server_port=int(os.getenv("GRADIO_SERVER_PORT", "7860")),
173
- share=False)
 
 
 
 
 
 
 
 
 
37
  fname = os.path.basename(p)
38
  filetype = detect_filetype(fname, raw_bytes)
39
 
40
+ # 1) テキスト抽出
41
  if filetype in {"pdf", "image"}:
42
  text = extract_text_with_openai(raw_bytes, filename=fname, filetype=filetype)
43
  else:
 
46
 
47
  raw_texts.append({"filename": fname, "text": text})
48
 
49
+ # 2) 構造化 → 3) ルール正規化
50
  structured = structure_with_openai(text)
51
  normalized = normalize_resume({
52
  "work_experience": structured.get("work_experience_raw", ""),
 
61
  "normalized": normalized,
62
  })
63
 
64
+ # 4) 複数ファイル統合
65
  merged = merge_normalized_records([r["normalized"] for r in partial_records])
66
 
67
+ # 5) スキル抽出
68
  merged_text = "\n\n".join([r["text"] for r in partial_records])
69
  skills = extract_skills(merged_text, {
70
  "work_experience": merged.get("raw_sections", {}).get("work_experience", ""),
 
73
  "skills": ", ".join(merged.get("skills", [])),
74
  })
75
 
76
+ # 6) 匿名化
77
  anonymized_text, anon_map = anonymize_text(merged_text)
78
  anon_pdf_bytes = render_anonymized_pdf(anonymized_text)
79
 
80
+ # 7) 品質スコア
81
  score = compute_quality_score(merged_text, merged)
82
 
83
+ # 8) 要約
84
  summaries = summarize_with_openai(merged_text)
85
 
86
+ # 9) 構造化出力
87
  result_json = {
88
  "candidate_id": candidate_id or hashlib.sha256(merged_text.encode("utf-8")).hexdigest()[:16],
89
  "files": [os.path.basename(p) for p in filepaths],
 
95
  "notes": additional_notes,
96
  }
97
 
98
+ # 10) HF Datasets 保存(任意)
99
  dataset_repo = os.environ.get("DATASET_REPO")
100
  commit_info = None
101
  if dataset_repo:
 
111
 
112
  anon_pdf = (result_json["candidate_id"] + ".anon.pdf", anon_pdf_bytes)
113
 
114
+ # 重要:コンポーネントはすべて文字列/ファイル(dictは返さない)
115
  return (
116
  json.dumps(result_json, ensure_ascii=False, indent=2),
117
  json.dumps(skills, ensure_ascii=False, indent=2),
 
128
  gr.Markdown(f"# {APP_TITLE}\n複数ファイルを統合→OpenAIで読み込み/構造化/要約→匿名化→Datasets保存")
129
 
130
  with gr.Row():
131
+ # Docker/サーバで取り回しやすいように filepath を採用
132
  in_files = gr.Files(
133
  label="レジュメ類 (PDF/画像/Word/テキスト) 複数可",
134
  file_count="multiple",
135
  file_types=[".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".bmp", ".docx", ".txt"],
136
+ type="filepath",
137
  )
138
  candidate_id = gr.Textbox(label="候補者ID(任意。未入力なら自動生成)")
139
  notes = gr.Textbox(label="補足メモ(任意)", lines=3)
 
144
  out_json = gr.Code(label="統合出力 (JSON)")
145
 
146
  with gr.Tab("抽出スキル"):
147
+ # ★ gr.JSON を排除(スキーマ生成バグ回避)
148
  out_skills = gr.Code(label="スキル一覧 (JSON)")
149
 
150
  with gr.Tab("品質スコア"):
 
169
 
170
 
171
  if __name__ == "__main__":
172
+ # ヘッドレス/プロキシ対応
173
+ server_name = os.getenv("GRADIO_SERVER_NAME", "0.0.0.0")
174
+ server_port = int(os.getenv("PORT", os.getenv("GRADIO_SERVER_PORT", "7860")))
175
+ share_env = os.getenv("GRADIO_SHARE", "false").lower() == "true"
176
+
177
+ demo.launch(
178
+ server_name=server_name,
179
+ server_port=server_port,
180
+ share=share_env,
181
+ inbrowser=False,
182
+ show_error=True,
183
+ )