GuXiaopeng commited on
Commit
2460c83
·
verified ·
1 Parent(s): 1bfb3eb

Update core/qualitative_engine.py

Browse files
Files changed (1) hide show
  1. core/qualitative_engine.py +19 -6
core/qualitative_engine.py CHANGED
@@ -1,6 +1,8 @@
1
  # -*- coding: utf-8 -*-
2
  import json
3
  import logging
 
 
4
 
5
  class QualitativeEngine:
6
  def __init__(self, agent):
@@ -9,24 +11,36 @@ class QualitativeEngine:
9
  def resolve_qualitative_data(self, topic, keywords, raw_interviews=""):
10
  """
11
  核心逻辑:解析真实访谈数据,或在无数据时模拟 ASQ 级别的定性数据结构表。
 
12
  """
13
  if raw_interviews and len(raw_interviews) > 100:
14
  logging.info("📝 检测到用户上传访谈记录,正在通过 DeepSeek-Reasoner 进行深度主题萃取...")
15
  prompt = f"Topic: {topic}. Extract the 15 most powerful, representative quotes from the following interview/field text. Organize into a Gioia-style coding structure. Return ONLY a valid JSON array of objects with keys: 'theme' (2nd-order), 'concept' (1st-order), and 'quote' (exact words)."
16
- response = self.agent.call_deepseek("You are an expert qualitative analyst.", f"DATA:\n{raw_interviews[:30000]}", model_name="deepseek-reasoner")
 
 
 
 
 
 
 
 
17
  else:
18
  logging.info("⚙️ 未检测到真实访谈记录,正在通过蒙特卡洛引擎模拟高质量定性编码树防幻觉...")
19
  prompt = f"Topic: {topic}. Keywords: {keywords}. As an ASQ researcher, simulate a rigorous set of qualitative data for this study. Provide 12 highly realistic, human-sounding representative interview quotes. Group them into emergent 1st-order concepts and 2nd-order themes. Return ONLY a valid JSON array of objects with keys: 'theme', 'concept', 'quote'."
20
- response = self.agent.call_deepseek("You are an expert qualitative analyst.", prompt, model_name="deepseek-chat")
 
 
 
 
 
21
 
22
  data = self.agent._extract_json_from_text(response)
23
 
24
- # 容错处理
25
  if not data:
26
  logging.error("❌ 定性数据 JSON 解析失败,回退至默认模拟数据。")
27
- return "### Table: Qualitative Coding Structure\n| 2nd-order Theme | 1st-order Concept | Representative Quote |\n| :--- | :--- | :--- |\n| Sensemaking | Initial Confusion | \"We really didn't know how to adapt to the new framework.\" [QUOTE-01] |"
28
 
29
- # 兼容 JSON 格式 (字典或列表)
30
  if isinstance(data, dict):
31
  items = data.get("data", data.get("quotes", []))
32
  elif isinstance(data, list):
@@ -34,7 +48,6 @@ class QualitativeEngine:
34
  else:
35
  items = []
36
 
37
- # 转换为 Markdown 表格,供流水线作为事实锚点注入
38
  md = "### Table: Qualitative Coding Structure (Data Evidence)\n| 2nd-order Theme | 1st-order Concept | Representative Quote |\n| :--- | :--- | :--- |\n"
39
  for i, item in enumerate(items[:15]):
40
  q = str(item.get("quote", "")).replace('"', "'").replace("\n", " ")
 
1
  # -*- coding: utf-8 -*-
2
  import json
3
  import logging
4
+ import re
5
+ import streamlit as st
6
 
7
  class QualitativeEngine:
8
  def __init__(self, agent):
 
11
  def resolve_qualitative_data(self, topic, keywords, raw_interviews=""):
12
  """
13
  核心逻辑:解析真实访谈数据,或在无数据时模拟 ASQ 级别的定性数据结构表。
14
+ 引入流式状态机,防止 WebSocket 假死超时。
15
  """
16
  if raw_interviews and len(raw_interviews) > 100:
17
  logging.info("📝 检测到用户上传访谈记录,正在通过 DeepSeek-Reasoner 进行深度主题萃取...")
18
  prompt = f"Topic: {topic}. Extract the 15 most powerful, representative quotes from the following interview/field text. Organize into a Gioia-style coding structure. Return ONLY a valid JSON array of objects with keys: 'theme' (2nd-order), 'concept' (1st-order), and 'quote' (exact words)."
19
+
20
+ # [修复点 1] 改用流式渲染,保活网关连接
21
+ with st.status("🧠 正在使用 R1 模型深度萃取访谈语录 (耗时较长,请观察下方思考流以防断连)...", expanded=True) as status:
22
+ ph = st.empty()
23
+ response = ph.write_stream(self.agent.stream_deepseek("You are an expert qualitative analyst.", f"DATA:\n{raw_interviews[:30000]}", model_name="deepseek-reasoner"))
24
+ status.update(label="✅ 访谈主题萃取完成!", state="complete", expanded=False)
25
+
26
+ # 清理流式输出中带有的 think 标签
27
+ response = re.sub(r'<think>.*?</think>', '', response, flags=re.DOTALL).strip()
28
  else:
29
  logging.info("⚙️ 未检测到真实访谈记录,正在通过蒙特卡洛引擎模拟高质量定性编码树防幻觉...")
30
  prompt = f"Topic: {topic}. Keywords: {keywords}. As an ASQ researcher, simulate a rigorous set of qualitative data for this study. Provide 12 highly realistic, human-sounding representative interview quotes. Group them into emergent 1st-order concepts and 2nd-order themes. Return ONLY a valid JSON array of objects with keys: 'theme', 'concept', 'quote'."
31
+
32
+ # [修复点 2] 模拟过程同样流式化
33
+ with st.status("⚙️ 正在通过 V3 模型极速模拟定性编码树...", expanded=True) as status:
34
+ ph = st.empty()
35
+ response = ph.write_stream(self.agent.stream_deepseek("You are an expert qualitative analyst.", prompt, model_name="deepseek-chat"))
36
+ status.update(label="✅ 模拟定性编码树构建完成!", state="complete", expanded=False)
37
 
38
  data = self.agent._extract_json_from_text(response)
39
 
 
40
  if not data:
41
  logging.error("❌ 定性数据 JSON 解析失败,回退至默认模拟数据。")
42
+ return "### Table: Qualitative Coding Structure\n| 2nd-order Theme | 1st-order Concept | Representative Quote |\n| :--- | :--- | :--- |\n| Sensemaking | Initial Confusion | \"We really didn't know how to adapt to the new framework.\" [QUOTE-01] |", "⚠️ 数据解析出现偏差,已启用降级保护预案。"
43
 
 
44
  if isinstance(data, dict):
45
  items = data.get("data", data.get("quotes", []))
46
  elif isinstance(data, list):
 
48
  else:
49
  items = []
50
 
 
51
  md = "### Table: Qualitative Coding Structure (Data Evidence)\n| 2nd-order Theme | 1st-order Concept | Representative Quote |\n| :--- | :--- | :--- |\n"
52
  for i, item in enumerate(items[:15]):
53
  q = str(item.get("quote", "")).replace('"', "'").replace("\n", " ")