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

Updated structure v1.1

Browse files
Files changed (4) hide show
  1. app.py +17 -22
  2. core/interviewer.py +10 -21
  3. core/mbti_analyzer.py +9 -7
  4. core/utils.py +0 -1
app.py CHANGED
@@ -1,16 +1,13 @@
1
  # app.py
2
  import gradio as gr
3
- import asyncio
4
  from core.utils import generate_first_question
5
  from core.mbti_analyzer import analyze_mbti
6
  from core.interviewer import generate_question
7
 
8
- # --------------------------------------------------------------
9
- # Асинхронная функция для стриминга ответов
10
- # --------------------------------------------------------------
11
- async def analyze_and_ask_stream(user_text, prev_count, user_id="default_user"):
12
  if not user_text.strip():
13
- yield gr.update(value="⚠️ Введите ответ."), gr.update(), gr.update()
14
  return
15
 
16
  try:
@@ -19,20 +16,19 @@ async def analyze_and_ask_stream(user_text, prev_count, user_id="default_user"):
19
  n = 1
20
  counter = f"{n}/30"
21
 
22
- yield gr.update(), gr.update(value="⏳ Анализируем..."), gr.update(value=counter)
23
-
24
- # Параллельные задачи
25
- mbti_task = asyncio.create_task(analyze_mbti(user_text))
26
- interviewer_task = asyncio.create_task(generate_question(user_id, user_text))
27
-
28
- # Сначала MBTI
29
- mbti_text = await mbti_task
30
- yield gr.update(value=mbti_text), gr.update(value="💭 Интервьюер думает..."), gr.update(value=counter)
31
-
32
- # Затем вопрос
33
- next_question = await interviewer_task
34
- yield gr.update(value=mbti_text), gr.update(value=next_question), gr.update(value=counter)
35
 
 
 
 
 
 
 
36
 
37
  # --------------------------------------------------------------
38
  # Gradio интерфейс
@@ -53,9 +49,8 @@ with gr.Blocks(theme=gr.themes.Soft(), title="MBTI Personality Interviewer") as
53
  interviewer_out = gr.Textbox(label="💬 Следующий вопрос от интервьюера", lines=3)
54
  progress = gr.Textbox(label="⏳ Прогресс", value="0/30")
55
 
56
- btn.click(analyze_and_ask_stream, inputs=[inp, progress], outputs=[mbti_out, interviewer_out, progress])
57
 
58
- # Первый вопрос при загрузке
59
  demo.load(lambda: ("", generate_first_question(), "0/30"), inputs=None, outputs=[mbti_out, interviewer_out, progress])
60
 
61
- demo.queue(streaming=True, max_size=20).launch(server_name="0.0.0.0", server_port=7860)
 
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:
 
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 интерфейс
 
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)
core/interviewer.py CHANGED
@@ -4,13 +4,9 @@ from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
4
 
5
  INTERVIEWER_MODEL = "f3nsmart/TinyLlama-MBTI-Interviewer-LoRA"
6
 
7
- # Инициализация
8
  tokenizer = AutoTokenizer.from_pretrained(INTERVIEWER_MODEL)
9
- model = AutoModelForCausalLM.from_pretrained(
10
- INTERVIEWER_MODEL,
11
- torch_dtype="auto",
12
- device_map="auto"
13
- )
14
  llm_pipe = pipeline(
15
  "text-generation",
16
  model=model,
@@ -20,27 +16,20 @@ llm_pipe = pipeline(
20
  top_p=0.9,
21
  )
22
 
23
- # Память для пользователей
24
  user_memory = {}
25
 
26
  def clean_question(text: str) -> str:
27
- """Удаляет инструкции, оставляя только вопрос"""
28
- text = text.strip().split("\n")[0]
29
- text = text.strip('"').strip("'")
30
  bad_tokens = ["user:", "assistant:", "instruction", "interviewer", "system:"]
31
  for bad in bad_tokens:
32
  if bad.lower() in text.lower():
33
  text = text.split(bad)[-1].strip()
34
  if not text.endswith("?"):
35
  text += "?"
36
- if len(text.split()) < 3:
37
- return "What do you usually enjoy doing in your free time?"
38
- return text.strip()
39
 
40
- async def generate_question(user_id: str, user_text: str) -> str:
41
- """
42
- Генерирует новый вопрос с учётом предыдущих.
43
- """
44
  prev_qs = user_memory.get(user_id, [])
45
  prev_joined = "; ".join(prev_qs) if prev_qs else "None"
46
 
@@ -53,8 +42,8 @@ async def generate_question(user_id: str, user_text: str) -> str:
53
  f"Interviewer:"
54
  )
55
 
56
- loop = asyncio.get_event_loop()
57
- raw = await loop.run_in_executor(None, lambda: llm_pipe(prompt)[0]["generated_text"])
58
  question = clean_question(raw)
59
 
60
  valid_starts = ("What", "Why", "How", "When")
@@ -62,5 +51,5 @@ async def generate_question(user_id: str, user_text: str) -> str:
62
  question = "What motivates you to do the things you enjoy most?"
63
 
64
  prev_qs.append(question)
65
- user_memory[user_id] = prev_qs[-10:] # храним последние 10
66
- return question
 
4
 
5
  INTERVIEWER_MODEL = "f3nsmart/TinyLlama-MBTI-Interviewer-LoRA"
6
 
 
7
  tokenizer = AutoTokenizer.from_pretrained(INTERVIEWER_MODEL)
8
+ model = AutoModelForCausalLM.from_pretrained(INTERVIEWER_MODEL, torch_dtype="auto", device_map="auto")
9
+
 
 
 
10
  llm_pipe = pipeline(
11
  "text-generation",
12
  model=model,
 
16
  top_p=0.9,
17
  )
18
 
 
19
  user_memory = {}
20
 
21
  def clean_question(text: str) -> str:
22
+ text = text.strip().split("\n")[0].strip('"').strip("'")
 
 
23
  bad_tokens = ["user:", "assistant:", "instruction", "interviewer", "system:"]
24
  for bad in bad_tokens:
25
  if bad.lower() in text.lower():
26
  text = text.split(bad)[-1].strip()
27
  if not text.endswith("?"):
28
  text += "?"
29
+ return text if len(text.split()) > 3 else "What do you usually enjoy doing in your free time?"
 
 
30
 
31
+ def generate_question(user_id: str, user_text: str):
32
+ """Генератор вопроса (стриминг)."""
 
 
33
  prev_qs = user_memory.get(user_id, [])
34
  prev_joined = "; ".join(prev_qs) if prev_qs else "None"
35
 
 
42
  f"Interviewer:"
43
  )
44
 
45
+ yield "💭 Interviewer is thinking..."
46
+ raw = llm_pipe(prompt)[0]["generated_text"]
47
  question = clean_question(raw)
48
 
49
  valid_starts = ("What", "Why", "How", "When")
 
51
  question = "What motivates you to do the things you enjoy most?"
52
 
53
  prev_qs.append(question)
54
+ user_memory[user_id] = prev_qs[-10:]
55
+ yield question
core/mbti_analyzer.py CHANGED
@@ -5,13 +5,15 @@ import asyncio
5
  MBTI_MODEL = "f3nsmart/MBTIclassifier"
6
  mbti_pipe = pipeline("text-classification", model=MBTI_MODEL, return_all_scores=True)
7
 
8
- async def analyze_mbti(user_text: str) -> str:
9
- """
10
- Асинхронный анализ текста на MBTI типы.
11
- Возвращает 3 лучших типа с их вероятностями.
12
- """
13
  loop = asyncio.get_event_loop()
14
- res = await loop.run_in_executor(None, lambda: mbti_pipe(user_text)[0])
 
 
 
 
 
15
  res_sorted = sorted(res, key=lambda x: x["score"], reverse=True)
16
  mbti_text = "\n".join([f"{r['label']} → {r['score']:.3f}" for r in res_sorted[:3]])
17
- return mbti_text
 
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
core/utils.py CHANGED
@@ -1,5 +1,4 @@
1
  # core/utils.py
2
 
3
  def generate_first_question() -> str:
4
- """Первый вопрос фиксированный"""
5
  return "What do you usually enjoy doing in your free time?"
 
1
  # core/utils.py
2
 
3
  def generate_first_question() -> str:
 
4
  return "What do you usually enjoy doing in your free time?"