SeaWolf-AI commited on
Commit
bdcd5fc
ยท
verified ยท
1 Parent(s): 42091d5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -29
app.py CHANGED
@@ -58,45 +58,87 @@ def parse_think_blocks(text: str) -> tuple[str, str]:
58
  m = re.search(r"<think>(.*?)</think>\s*", text, re.DOTALL)
59
  return (m.group(1).strip(), text[m.end():].strip()) if m else ("", text)
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  def format_response(raw: str) -> str:
62
- # 1. <think>...</think> ์™„๋ฃŒ๋œ ๊ฒฝ์šฐ
63
  chain, answer = parse_think_blocks(raw)
64
  if chain:
65
- lines = chain.split("\n")
66
- quoted = "\n".join(f"> {l}" for l in lines)
67
- block = (
68
  "<details>\n"
69
  "<summary>๐Ÿง  Reasoning Chain โ€” click to expand</summary>\n\n"
70
- f"{quoted}\n\n"
71
  "</details>\n\n"
 
72
  )
73
- return block + answer
74
- # 2. <think> ์—ด๋ฆผ but ๋‹ซํžˆ์ง€ ์•Š์Œ โ€” ์ŠคํŠธ๋ฆฌ๋ฐ ์ค‘
75
  if "<think>" in raw and "</think>" not in raw:
76
  think_len = len(raw) - raw.index("<think>") - 7
77
  return f"๐Ÿง  Reasoning... ({think_len} chars)"
78
- # 3. NIPA ์—”๋“œํฌ์ธํŠธ: ํ‰๋ฌธ "Thinking Process:" ๊ฐ์ง€
79
- think_markers = ["Thinking Process:", "Thinking process:", "**Thinking Process", "1. **Analyze"]
80
- for marker in think_markers:
81
- if marker in raw:
82
- # ์•„์ง ์ตœ์ข… ๋‹ต๋ณ€์ด ์•ˆ ๋‚˜์™”์œผ๋ฉด ์บ๋ฆญํ„ฐ ์ˆ˜๋งŒ ํ‘œ์‹œ
83
- # ์ตœ์ข… ๋‹ต๋ณ€ ์‹œ์ž‘ ํŒจํ„ด: ํ•œ๊ตญ์–ด ์ธ์‚ฌ, ์˜์–ด ์ธ์‚ฌ, ๋ฒˆํ˜ธ ์—†๋Š” ์ผ๋ฐ˜ ๋ฌธ์žฅ
84
- answer_patterns = [
85
- "\n\n์•ˆ๋…•", "\n\n๋ฐ˜๊ฐ‘", "\n\n๋„ค,", "\n\n Hello", "\n\nHi", "\n\nI ",
86
- "\n\n---\n", "\n\n**Answer", "\n\n**Response",
87
- ]
88
- for ap in answer_patterns:
89
- idx = raw.find(ap)
90
- if idx > 0:
91
- think_part = raw[:idx].strip()
92
- answer_part = raw[idx:].strip()
93
- return (
94
- f"<details>\n"
95
- f"<summary>๐Ÿง  Reasoning Chain ({len(think_part)} chars)</summary>\n\n"
96
- f"{think_part}\n\n"
97
- f"</details>\n\n"
98
- f"{answer_part}"
99
- )
100
  # ์•„์ง ๋‹ต๋ณ€ ์•ˆ ๋‚˜์˜ด โ€” ์บ๋ฆญํ„ฐ ์ˆ˜๋งŒ
101
  return f"๐Ÿง  Reasoning... ({len(raw)} chars)"
102
  return raw
 
58
  m = re.search(r"<think>(.*?)</think>\s*", text, re.DOTALL)
59
  return (m.group(1).strip(), text[m.end():].strip()) if m else ("", text)
60
 
61
+ def _is_thinking_line(line: str) -> bool:
62
+ """ํ•œ ์ค„์ด reasoning/thinking์ธ์ง€ ๊ฐ์ง€"""
63
+ l = line.strip()
64
+ if not l:
65
+ return True # ๋นˆ ์ค„์€ thinking ๋ธ”๋ก์— ํฌํ•จ
66
+ # ์˜์–ด reasoning ํŒจํ„ด
67
+ think_starts = [
68
+ "The user", "the user", "This is", "this is", "I should", "I need to",
69
+ "Let me", "let me", "My task", "my task", "I'll ", "I will",
70
+ "Since ", "since ", "Now,", "now,", "So,", "so,", "First,", "first,",
71
+ "Okay", "okay", "Alright", "Hmm", "Wait", "Actually",
72
+ "The question", "the question", "The input", "the input",
73
+ "The request", "the request", "The prompt", "the prompt",
74
+ "Thinking Process", "Thinking process", "**Thinking",
75
+ "Step ", "step ", "Approach:", "Analysis:", "Reasoning:",
76
+ "1. **", "2. **", "3. **", "4. **", "5. **",
77
+ ]
78
+ for s in think_starts:
79
+ if l.startswith(s):
80
+ return True
81
+ # ๊ธ€๋จธ๋ฆฌ ๊ธฐํ˜ธ + ์˜์–ด reasoning
82
+ if l.startswith(("- ", "* ", "โ—‹ ")) and any(c.isascii() and c.isalpha() for c in l[:20]):
83
+ if not any(ord(c) > 0x1100 for c in l[:30]): # ํ•œ๊ธ€ ์—†์œผ๋ฉด thinking
84
+ return True
85
+ return False
86
+
87
+
88
+ def _split_thinking_answer(raw: str) -> tuple:
89
+ """์‘๋‹ต์—์„œ thinking ๋ถ€๋ถ„๊ณผ ์‹ค์ œ ๋‹ต๋ณ€์„ ๋ถ„๋ฆฌ"""
90
+ lines = raw.split("\n")
91
+ answer_start = -1
92
+
93
+ for i, line in enumerate(lines):
94
+ if not _is_thinking_line(line):
95
+ # ํ•œ๊ธ€/๋น„ASCII๊ฐ€ ํฌํ•จ๋œ ์‹ค์ œ ๋‹ต๋ณ€ ์‹œ์ž‘์ 
96
+ if any(ord(c) > 0x1100 for c in line.strip()[:10]):
97
+ answer_start = i
98
+ break
99
+ # ๋˜๋Š” ๋นˆ์ค„ 2๊ฐœ ์ดํ›„ ์˜์–ด ๋‹ต๋ณ€
100
+ if i > 2 and not _is_thinking_line(line):
101
+ # ์•ž์˜ 2์ค„์ด ๋นˆ์ค„์ด๋ฉด ๋‹ต๋ณ€ ์‹œ์ž‘
102
+ if all(not lines[j].strip() for j in range(max(0,i-2), i)):
103
+ answer_start = i
104
+ break
105
+
106
+ if answer_start > 0:
107
+ thinking = "\n".join(lines[:answer_start]).strip()
108
+ answer = "\n".join(lines[answer_start:]).strip()
109
+ return thinking, answer
110
+
111
+ return "", raw
112
+
113
+
114
  def format_response(raw: str) -> str:
115
+ # 1. <think>...</think> ์™„๋ฃŒ
116
  chain, answer = parse_think_blocks(raw)
117
  if chain:
118
+ return (
 
 
119
  "<details>\n"
120
  "<summary>๐Ÿง  Reasoning Chain โ€” click to expand</summary>\n\n"
121
+ f"{chain}\n\n"
122
  "</details>\n\n"
123
+ f"{answer}"
124
  )
125
+ # 2. <think> ์—ด๋ฆผ but ๋‹ซํžˆ์ง€ ์•Š์Œ
 
126
  if "<think>" in raw and "</think>" not in raw:
127
  think_len = len(raw) - raw.index("<think>") - 7
128
  return f"๐Ÿง  Reasoning... ({think_len} chars)"
129
+ # 3. ํ‰๋ฌธ thinking ๊ฐ์ง€ (NIPA ์—”๋“œํฌ์ธํŠธ)
130
+ first_line = raw.strip().split("\n")[0] if raw.strip() else ""
131
+ if _is_thinking_line(first_line) and len(raw) > 20:
132
+ thinking, answer = _split_thinking_answer(raw)
133
+ if thinking and answer:
134
+ return (
135
+ f"<details>\n"
136
+ f"<summary>๐Ÿง  Reasoning Chain ({len(thinking)} chars)</summary>\n\n"
137
+ f"{thinking}\n\n"
138
+ f"</details>\n\n"
139
+ f"{answer}"
140
+ )
141
+ elif thinking and not answer:
 
 
 
 
 
 
 
 
 
142
  # ์•„์ง ๋‹ต๋ณ€ ์•ˆ ๋‚˜์˜ด โ€” ์บ๋ฆญํ„ฐ ์ˆ˜๋งŒ
143
  return f"๐Ÿง  Reasoning... ({len(raw)} chars)"
144
  return raw