QAway-to commited on
Commit
a8db2c5
·
1 Parent(s): aaa09c9

Updated structure v1.2

Browse files
app.py CHANGED
@@ -1,56 +1,37 @@
1
- # app.py
2
  import gradio as gr
3
- from core.utils import generate_first_question
4
- from core.mbti_analyzer import analyze_mbti
5
- from core.interviewer import generate_question
6
-
7
- def analyze_and_ask(user_text, prev_count):
8
- """Пошаговый генератор — стриминг без async и без streaming=True."""
9
- if not user_text.strip():
10
- yield "⚠️ Please enter your answer.", "", prev_count
11
- return
12
-
13
- try:
14
- n = int(prev_count.split("/")[0]) + 1
15
- except Exception:
16
- n = 1
17
- counter = f"{n}/30"
18
-
19
- # 1️⃣ Шаг 1 — анализ
20
- mbti_gen = analyze_mbti(user_text)
21
- mbti_text = ""
22
- for chunk in mbti_gen:
23
- mbti_text = chunk
24
- yield mbti_text, "💭 Interviewer is thinking...", counter
25
-
26
- # 2️⃣ Шаг 2 — вопрос
27
- interviewer_gen = generate_question("default_user", user_text)
28
- next_q = ""
29
- for chunk in interviewer_gen:
30
- next_q = chunk
31
- yield mbti_text, next_q, counter
32
-
33
- # --------------------------------------------------------------
34
- # Gradio интерфейс
35
- # --------------------------------------------------------------
36
- with gr.Blocks(theme=gr.themes.Soft(), title="MBTI Personality Interviewer") as demo:
37
- gr.Markdown("## 🧠 MBTI Personality Interviewer\nОпредели личностный тип и получи следующий вопрос от интервьюера.")
38
-
39
- with gr.Row():
40
- with gr.Column(scale=1):
41
- inp = gr.Textbox(
42
- label="Ваш ответ",
43
- placeholder="Например: I enjoy working with people and organizing events.",
44
- lines=4
45
- )
46
- btn = gr.Button("Анализировать и задать новый вопрос", variant="primary")
47
- with gr.Column(scale=1):
48
- mbti_out = gr.Textbox(label="📊 Анализ MBTI", lines=4)
49
- interviewer_out = gr.Textbox(label="💬 Следующий вопрос от интервьюера", lines=3)
50
- progress = gr.Textbox(label="⏳ Прогресс", value="0/30")
51
-
52
- btn.click(analyze_and_ask, inputs=[inp, progress], outputs=[mbti_out, interviewer_out, progress])
53
-
54
- demo.load(lambda: ("", generate_first_question(), "0/30"), inputs=None, outputs=[mbti_out, interviewer_out, progress])
55
-
56
- demo.queue(max_size=20).launch(server_name="0.0.0.0", server_port=7860)
 
 
1
  import gradio as gr
2
+ from core.interviewer_phi3 import generate_question, categories
3
+ from core.analyzer_mbti import classify_answer
4
+
5
+ state = {"i": 0, "history": []}
6
+
7
+ def next_step(user_answer):
8
+ # Сохраняем ответ
9
+ if user_answer.strip():
10
+ state["history"].append(user_answer)
11
+ else:
12
+ return "⚠️ Please type your answer.", ""
13
+
14
+ # Анализ MBTI
15
+ traits = classify_answer(user_answer)
16
+ traits_text = "\n".join([f"{t['label']} → {t['score']:.3f}" for t in traits])
17
+
18
+ # Следующий вопрос
19
+ if state["i"] < len(categories):
20
+ cat = categories[state["i"]]
21
+ q = generate_question(state["history"], cat)
22
+ state["i"] += 1
23
+ else:
24
+ q = "✅ Interview finished. Personality summary calculated."
25
+
26
+ return traits_text, q
27
+
28
+ with gr.Blocks(theme=gr.themes.Soft()) as demo:
29
+ gr.Markdown("## 🧠 MBTI Interviewer (Phi-3)")
30
+ inp = gr.Textbox(label="Answer", lines=3)
31
+ btn = gr.Button("Next Question", variant="primary")
32
+ out1 = gr.Textbox(label="📊 MBTI Analysis", lines=3)
33
+ out2 = gr.Textbox(label="💬 Next Question", lines=3)
34
+ btn.click(fn=next_step, inputs=inp, outputs=[out1, out2])
35
+ demo.load(lambda: ("", generate_question([], categories[0])), outputs=out2)
36
+
37
+ demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
core/analyzer_mbti.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import pipeline
2
+
3
+ MBTI_MODEL = "f3nsmart/MBTIclassifier"
4
+ classifier = pipeline("text-classification", model=MBTI_MODEL, return_all_scores=True)
5
+
6
+ def classify_answer(answer: str):
7
+ res = classifier(answer)[0]
8
+ sorted_res = sorted(res, key=lambda x: x["score"], reverse=True)
9
+ return sorted_res[:3] # top 3 traits
core/interviewer_phi3.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
2
+ import random, json, os
3
+
4
+ MODEL_NAME = "microsoft/Phi-3-mini-4k-instruct"
5
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
6
+ model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, torch_dtype="auto", device_map="auto")
7
+
8
+ generator = pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=70, temperature=0.7, top_p=0.9)
9
+
10
+ DATA_PATH = "data"
11
+ categories = sorted([f.replace(".json", "") for f in os.listdir(DATA_PATH) if f.endswith(".json")])
12
+
13
+ def load_category_sample(cat_name):
14
+ path = os.path.join(DATA_PATH, f"{cat_name}.json")
15
+ with open(path, "r", encoding="utf-8") as f:
16
+ data = json.load(f)
17
+ return random.choice(data).get("instruction", "")
18
+
19
+ def generate_question(history, current_cat):
20
+ """
21
+ Сценарий генерации вопроса по текущей категории MBTI.
22
+ """
23
+ sample = load_category_sample(current_cat)
24
+ hist_text = "\n".join([f"Q{i//2+1 if i%2==0 else ''}: {h}" for i, h in enumerate(history)])
25
+ prompt = (
26
+ f"You're generating interview questions for MBTI testing.\n"
27
+ f"Previous dialogue:\n{hist_text}\n"
28
+ f"Generate one new open-ended question related to {current_cat.replace('_', ' ')} "
29
+ f"based on this example:\n'{sample}'\n"
30
+ f"Do not repeat or rephrase previous ones. Output only the question text."
31
+ )
32
+ output = generator(prompt)[0]["generated_text"]
33
+ q = output.split("\n")[-1].strip()
34
+ return q
core/mbti_analyzer.py DELETED
@@ -1,19 +0,0 @@
1
- # core/mbti_analyzer.py
2
- from transformers import pipeline
3
- import asyncio
4
-
5
- MBTI_MODEL = "f3nsmart/MBTIclassifier"
6
- mbti_pipe = pipeline("text-classification", model=MBTI_MODEL, return_all_scores=True)
7
-
8
- async def analyze_mbti_async(user_text: str):
9
- """Асинхронный MBTI-анализ."""
10
- loop = asyncio.get_event_loop()
11
- return await loop.run_in_executor(None, lambda: mbti_pipe(user_text)[0])
12
-
13
- def analyze_mbti(user_text: str):
14
- """Генератор для стриминга результата."""
15
- yield "⏳ Analyzing personality traits..."
16
- res = asyncio.run(analyze_mbti_async(user_text))
17
- res_sorted = sorted(res, key=lambda x: x["score"], reverse=True)
18
- mbti_text = "\n".join([f"{r['label']} → {r['score']:.3f}" for r in res_sorted[:3]])
19
- yield mbti_text