sofiamak commited on
Commit
d99ae44
·
verified ·
1 Parent(s): 77f08ac

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +75 -27
app.py CHANGED
@@ -1,7 +1,7 @@
1
- import os, json, html, requests, re
2
  import gradio as gr
3
 
4
- APP_TITLE = "孙子你好(DeepSeek 直连·诊断版)"
5
 
6
  # 可通过 Secrets 覆盖:
7
  # DEEPSEEK_API_KEY = sk-xxxxxxxx
@@ -12,20 +12,28 @@ APP_TITLE = "孙子你好(DeepSeek 直连·诊断版)"
12
  MODEL_NAME = os.getenv("DEEPSEEK_MODEL", "deepseek-chat").strip() or "deepseek-chat"
13
 
14
  SYS_PROMPT = (
15
- "你是中文军师,严格依据《孙子兵法》为现实小问题给出策略。\n"
 
16
  "规则:\n"
17
- "1) 优先引用《孙子兵法》原文句子,并指明篇名(如:谋攻篇、虚实篇)。\n"
18
- "2) 如果无法百分之百确认出典或篇名,不要硬编,改为意译/思想要点,并标记 unsure=true。\n"
19
- "3) 仅输出 JSON,固定字段:\n"
20
- ' {\"chapter\":\"<篇名或空>\",\"quote\":\"<原文或意译>\",\"unsure\":false/true,'
21
- '\"insight\":\"<一句人话启示≤24字>\",\"action\":\"<一步可执行做法≤100字>\",'
22
- '\"speech\":\"<可直接对话的话术≤120字>\"}\n'
23
- "4) 风格:简洁、机智、委婉、有边界;不得人身攻击、威胁或违法建议。\n"
24
- "5) 严格仅输出 JSON,不要任何多余文字。"
 
 
 
 
 
 
25
  )
26
 
27
- # few-shot 用 json.dumps 生成,避免手写引号带来语法错误
28
  FEWSHOT = [
 
29
  {
30
  "role": "user",
31
  "content": "问题:老板临时要我通宵加班,我状态很差,怎么体面拒绝?只输出JSON。"
@@ -33,14 +41,15 @@ FEWSHOT = [
33
  {
34
  "role": "assistant",
35
  "content": json.dumps({
36
- "chapter": "虚实篇",
37
- "quote": "避实而击虚。",
38
  "unsure": False,
39
- "insight": "别硬碰命令,转打结果。",
40
- "action": "给出“今晚草稿/明早终版”二选一,引导选择后者以保质量和节奏。",
41
- "speech": "我今晚能出草稿,也能明早交更稳的终版。为保证质量,我建议后一种,您看呢?"
42
  }, ensure_ascii=False)
43
  },
 
44
  {
45
  "role": "user",
46
  "content": "问题:朋友借钱不还,怎样体面要回?只输出JSON。"
@@ -52,14 +61,46 @@ FEWSHOT = [
52
  "quote": "兵者,诡道也。",
53
  "unsure": False,
54
  "insight": "绕开硬催,设局顺势收回。",
55
- "action": "先说明自己在清账安排资金,再给“部分先还/分期”台阶,降低对抗。",
56
- "speech": "我这边在清账需要安排下,方便的话先转一部分?分期也行,别影响咱们交情。"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  }, ensure_ascii=False)
58
  }
59
  ]
60
 
61
  def call_deepseek(user_question: str, alt: bool = False) -> dict:
62
- """带精确诊断:自动尝试两个端点,页面/日志展示状态码与返回体。"""
63
  key = os.getenv("DEEPSEEK_API_KEY", "").strip()
64
  if not key:
65
  return {
@@ -77,7 +118,16 @@ def call_deepseek(user_question: str, alt: bool = False) -> dict:
77
  "https://api.deepseek.com/chat/completions",
78
  ]
79
 
80
- msgs = [{"role": "system", "content": SYS_PROMPT}] + FEWSHOT + [
 
 
 
 
 
 
 
 
 
81
  {"role": "user", "content": f"问题:{user_question} 只输出JSON。"}
82
  ]
83
 
@@ -97,7 +147,7 @@ def call_deepseek(user_question: str, alt: bool = False) -> dict:
97
  json=payload,
98
  timeout=60
99
  )
100
- print(f"[DeepSeek] endpoint={ep} status={r.status_code} model={MODEL_NAME}") # 写入 Runtime logs
101
 
102
  if r.status_code // 100 != 2:
103
  try:
@@ -113,19 +163,17 @@ def call_deepseek(user_question: str, alt: bool = False) -> dict:
113
  js = m.group(0) if m else content
114
  result = json.loads(js)
115
 
116
- # 规整长度,防止偶发超长
117
  return {
118
  "chapter": result.get("chapter", "")[:20],
119
- "quote": result.get("quote", "")[:160],
120
  "unsure": bool(result.get("unsure", False)),
121
  "insight": result.get("insight", "")[:40],
122
- "action": result.get("action", "")[:100],
123
- "speech": result.get("speech", "")[:120]
124
  }
125
  except Exception as e:
126
  last_err = f"{type(e).__name__}: {e}"
127
 
128
- # 两个端点都失败
129
  return {
130
  "chapter": "",
131
  "quote": "为避免误引,已隐藏原文与篇名(模型不确定出典)。",
 
1
+ import os, json, html, requests, re, random
2
  import gradio as gr
3
 
4
+ APP_TITLE = "孙子你好(DeepSeek 多样化·诊断版)"
5
 
6
  # 可通过 Secrets 覆盖:
7
  # DEEPSEEK_API_KEY = sk-xxxxxxxx
 
12
  MODEL_NAME = os.getenv("DEEPSEEK_MODEL", "deepseek-chat").strip() or "deepseek-chat"
13
 
14
  SYS_PROMPT = (
15
+ "你是中文军师,擅长将《孙子兵法》的智慧用于现实问题。\n"
16
+ "任务:针对用户的问题,从《孙子兵法》十三篇中找出最贴合的一章,引用原文(若能确定),并转化为现代生活策略。\n\n"
17
  "规则:\n"
18
+ "1. 优先根据问题性质挑选不同篇章:\n"
19
+ " - 计划/评估:〈始计篇〉〈作战篇〉\n"
20
+ " - 谈判/攻防:〈谋攻篇〉〈虚实篇〉\n"
21
+ " - 节奏/风险:〈军形篇〉〈兵势篇〉\n"
22
+ " - 主动出击/竞争:〈军争篇〉〈九变篇〉〈地形篇〉\n"
23
+ " - 困境/沟通:〈行军篇〉〈九地篇〉〈用间篇〉〈火攻篇〉\n"
24
+ "2. 若问题重复,尽量换不同篇章或换角度回答,保持多样性。\n"
25
+ "3. 若无法百分之百确认原文或篇名,不要硬编,改为思想意译并标记 unsure=true。\n"
26
+ "4. 严格仅输出 JSON,固定字段:\n"
27
+ " {\"chapter\":\"<篇名>\",\"quote\":\"<原文或思想>\",\"unsure\":false/true,"
28
+ "\"insight\":\"<一句人话启示≤24字>\",\"action\":\"<一步可执行做法≤100字>\","
29
+ "\"speech\":\"<直接可说的话术≤120字>\"}\n"
30
+ "5. 语气简洁、机智、委婉、有边界;不得人身攻击、威胁或违法建议。\n"
31
+ "6. 禁止输出 JSON 以外的任何文字。"
32
  )
33
 
34
+ # few-shot:覆盖多篇章,减少模型只用某一章的倾向
35
  FEWSHOT = [
36
+ # 加班 → 作战篇
37
  {
38
  "role": "user",
39
  "content": "问题:老板临时要我通宵加班,我状态很差,怎么体面拒绝?只输出JSON。"
 
41
  {
42
  "role": "assistant",
43
  "content": json.dumps({
44
+ "chapter": "作战篇",
45
+ "quote": "夫兵久而国利者,未之有也。",
46
  "unsure": False,
47
+ "insight": "避免持久消耗,保整体战力。",
48
+ "action": "提出“明早高质量交付”的替代方案,比熬夜更稳更可靠。",
49
+ "speech": "今晚赶出来质量可能不稳,我建议明早整理成终版,保证更可靠,您看可以吗?"
50
  }, ensure_ascii=False)
51
  },
52
+ # 借钱 → 始计篇
53
  {
54
  "role": "user",
55
  "content": "问题:朋友借钱不还,怎样体面要回?只输出JSON。"
 
61
  "quote": "兵者,诡道也。",
62
  "unsure": False,
63
  "insight": "绕开硬催,设局顺势收回。",
64
+ "action": "以“清账/安排资金”为由先要部分或分期,降低对抗。",
65
+ "speech": "我这边在清账需要安排下,能否先转一部分?分期也行,别影响咱们交情。"
66
+ }, ensure_ascii=False)
67
+ },
68
+ # 邻居噪音 → 行军篇
69
+ {
70
+ "role": "user",
71
+ "content": "问题:邻居太吵,怎么友好沟通?只输出JSON。"
72
+ },
73
+ {
74
+ "role": "assistant",
75
+ "content": json.dumps({
76
+ "chapter": "行军篇",
77
+ "quote": "知彼知己,百战不��。(通用于沟通前的情势判断)",
78
+ "unsure": True, # 行军篇原文无此句,标不确定,演示 unsure 机制
79
+ "insight": "先辨来源时机,再择机沟通。",
80
+ "action": "选非冲突时段,先体谅再提困扰,争取对方自觉收敛。",
81
+ "speech": "最近晚上声音有点明显,我怕打扰到楼上楼下。能否帮忙晚间稍微注意下?谢谢啦~"
82
+ }, ensure_ascii=False)
83
+ },
84
+ # 职场竞争 → 军争篇
85
+ {
86
+ "role": "user",
87
+ "content": "问题:同事跟我抢功劳,怎么应对?只输出JSON。"
88
+ },
89
+ {
90
+ "role": "assistant",
91
+ "content": json.dumps({
92
+ "chapter": "军争篇",
93
+ "quote": "以迂为直,以患为利。",
94
+ "unsure": False,
95
+ "insight": "不硬碰,转势为己用。",
96
+ "action": "会前先递交要点纪要和分工佐证,令功劳记录化、流程化。",
97
+ "speech": "我把这次我的负责点和关键产出提前发一份纪要,方便会里对齐,避免遗漏。"
98
  }, ensure_ascii=False)
99
  }
100
  ]
101
 
102
  def call_deepseek(user_question: str, alt: bool = False) -> dict:
103
+ """带精确诊断:自动尝试两个端点,页面/日志展示状态码与返回体;加入多样化提示。"""
104
  key = os.getenv("DEEPSEEK_API_KEY", "").strip()
105
  if not key:
106
  return {
 
118
  "https://api.deepseek.com/chat/completions",
119
  ]
120
 
121
+ # 多样化提示:鼓励换篇章/换角度
122
+ diversity_hint = random.choice([
123
+ "尽量避免重复使用同一篇章,尝试换篇章回答。",
124
+ "优先考虑《军形篇》《兵势篇》《九变篇》《地形篇》的角度。",
125
+ "如果问题可多解,换一个不同篇章来解释。",
126
+ "引用少见但贴合的篇章,保持回答多样性。",
127
+ "可从节奏、态势、资源、时机等不同维度选篇章。"
128
+ ])
129
+
130
+ msgs = [{"role": "system", "content": SYS_PROMPT + "\n" + diversity_hint}] + FEWSHOT + [
131
  {"role": "user", "content": f"问题:{user_question} 只输出JSON。"}
132
  ]
133
 
 
147
  json=payload,
148
  timeout=60
149
  )
150
+ print(f"[DeepSeek] endpoint={ep} status={r.status_code} model={MODEL_NAME}") # Runtime logs
151
 
152
  if r.status_code // 100 != 2:
153
  try:
 
163
  js = m.group(0) if m else content
164
  result = json.loads(js)
165
 
 
166
  return {
167
  "chapter": result.get("chapter", "")[:20],
168
+ "quote": result.get("quote", "")[:200],
169
  "unsure": bool(result.get("unsure", False)),
170
  "insight": result.get("insight", "")[:40],
171
+ "action": result.get("action", "")[:120],
172
+ "speech": result.get("speech", "")[:140]
173
  }
174
  except Exception as e:
175
  last_err = f"{type(e).__name__}: {e}"
176
 
 
177
  return {
178
  "chapter": "",
179
  "quote": "为避免误引,已隐藏原文与篇名(模型不确定出典)。",