openfree commited on
Commit
ad2752a
·
verified ·
1 Parent(s): a4ca8e9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +12 -302
app.py CHANGED
@@ -1,6 +1,5 @@
1
  import re
2
  import threading
3
- from collections import Counter
4
 
5
  import gradio as gr
6
  import spaces
@@ -8,7 +7,7 @@ import transformers
8
  from transformers import pipeline
9
 
10
  # 모델과 토크나이저 로딩
11
- model_name = "CohereForAI/c4ai-command-r7b-arabic-02-2025"
12
  if gr.NO_RELOAD:
13
  pipe = pipeline(
14
  "text-generation",
@@ -24,7 +23,6 @@ ANSWER_MARKER = "**답변**"
24
  rethink_prepends = [
25
  "자, 이제 다음을 파악해야 합니다 ",
26
  "제 생각에는 ",
27
- "잠시만요, 제 생각에는 ",
28
  "다음 사항이 맞는지 확인해 보겠습니다 ",
29
  "또한 기억해야 할 것은 ",
30
  "또 다른 주목할 점은 ",
@@ -32,190 +30,15 @@ rethink_prepends = [
32
  "이제 충분히 이해했다고 생각합니다 ",
33
  ]
34
 
35
- # 일반적인 추론 가이드 프롬프트
36
- general_reasoning_guide = """
37
- 이 문제를 해결하기 위한 체계적인 접근 방법을 사용하겠습니다:
38
-
39
- 1. 문제에서 제공된 모든 정보와 조건을 명확히 이해합니다.
40
- 2. 각 변수와 관계를 식별하고 필요한 방정식을 세웁니다.
41
- 3. 단계별로 계산을 수행하며, 각 단계의 결과를 확인합니다.
42
- 4. 중간 결과가 합리적인지 검토하며 진행합니다.
43
- 5. 최종 답안을 도출하고 문제의 요구사항을 충족하는지 확인합니다.
44
-
45
- 이제 문제를 풀어보겠습니다:
46
- """
47
-
48
- # 결과 추출 및 검증을 위한 함수들
49
- def extract_calculation_results(reasoning_text):
50
- """추론 과정에서 도출된 가능한 답안 결과를 추출합니다."""
51
- # 수치 결과 패턴 (다양한 표현 방식 고려)
52
- numeric_patterns = [
53
- r'결과는 (\d+[\.,]?\d*)',
54
- r'답(은|는|이) (\d+[\.,]?\d*)',
55
- r'정답(은|는|이) (\d+[\.,]?\d*)',
56
- r'답안(은|는|이) (\d+[\.,]?\d*)',
57
- r'수익(은|는|이) (\d+[\.,]?\d*)',
58
- r'값(은|는|이) (\d+[\.,]?\d*)',
59
- r'결론(은|는|이) (\d+[\.,]?\d*)',
60
- r'개수(는|은|가) (\d+[\.,]?\d*)',
61
- r'총 (\d+[\.,]?\d*)개',
62
- r'총액(은|는|이) (\d+[\.,]?\d*)',
63
- r'총합(은|는|이) (\d+[\.,]?\d*)',
64
- r'합계(는|은|가) (\d+[\.,]?\d*)',
65
- r'=\s*(\d+[\.,]?\d*)\s*$',
66
- r':\s*(\d+[\.,]?\d*)\s*$',
67
- r'총계:\s*(\d+[\.,]?\d*)',
68
- r'최종 결과:\s*(\d+[\.,]?\d*)',
69
- r'최종 값:\s*(\d+[\.,]?\d*)',
70
- r'최종 답변:\s*(\d+[\.,]?\d*)',
71
- ]
72
-
73
- # 단위를 포함한 패턴 (달러, 개, 세트 등)
74
- unit_patterns = [
75
- r'(\d+[\.,]?\d*)\s*(달러|원|유로|파운드|엔)',
76
- r'(\d+[\.,]?\d*)\s*(개|명|세트|쌍|팀|그룹)',
77
- r'(\d+[\.,]?\d*)\s*(분|시간|초|일|주|개월|년)',
78
- r'(\d+[\.,]?\d*)\s*(미터|킬로미터|센티미터|인치|피트)',
79
- r'(\d+[\.,]?\d*)\s*(그램|킬로그램|파운드|온스)',
80
- ]
81
-
82
- results = []
83
-
84
- # 숫자 결과 추출
85
- for pattern in numeric_patterns:
86
- matches = re.findall(pattern, reasoning_text, re.IGNORECASE)
87
- for match in matches:
88
- if isinstance(match, tuple):
89
- # 그룹이 여러 개인 경우 (첫 번째는 조사 등)
90
- value = match[-1] # 마지막 그룹이 숫자값
91
- else:
92
- value = match
93
- # 콤마 제거 및 소수점 처리
94
- value = value.replace(',', '')
95
- try:
96
- if '.' in value:
97
- results.append(float(value))
98
- else:
99
- results.append(int(value))
100
- except ValueError:
101
- continue
102
-
103
- # 단위가 포함된 결과 추출
104
- for pattern in unit_patterns:
105
- matches = re.findall(pattern, reasoning_text, re.IGNORECASE)
106
- for match in matches:
107
- value = match[0].replace(',', '')
108
- try:
109
- if '.' in value:
110
- results.append(float(value))
111
- else:
112
- results.append(int(value))
113
- except ValueError:
114
- continue
115
-
116
- # 마지막 문단에서 숫자만 추출 (최종 답변에 가까운 숫자)
117
- last_paragraph = reasoning_text.split('\n\n')[-1]
118
- numbers_in_last = re.findall(r'(\d+[\.,]?\d*)', last_paragraph)
119
- for num in numbers_in_last:
120
- num = num.replace(',', '')
121
- try:
122
- if '.' in num:
123
- results.append(float(num))
124
- else:
125
- results.append(int(num))
126
- except ValueError:
127
- continue
128
-
129
- return results
130
-
131
- def determine_best_result(results, full_reasoning):
132
- """가장 신뢰할 수 있는 결과를 결정합니다."""
133
- if not results:
134
- return None
135
-
136
- # 결과가 하나밖에 없으면 그것을 반환
137
- if len(set(results)) == 1:
138
- return results[0]
139
-
140
- # 빈도 기반 분석 (가장 자주 등장한 결과가 신뢰성이 높을 가능성)
141
- counter = Counter(results)
142
- most_common = counter.most_common()
143
-
144
- # 빈도가 높은 상위 결과들
145
- top_results = [result for result, count in most_common if count >= most_common[0][1] * 0.8]
146
-
147
- if len(top_results) == 1:
148
- return top_results[0]
149
-
150
- # 최종 결론 근처에 있는 결과에 더 높은 가중치 부여
151
- paragraphs = full_reasoning.split('\n\n')
152
- last_paragraphs = '\n\n'.join(paragraphs[-2:]) # 마지막 두 단락
153
-
154
- # 마지막 단락에서 등장하는 결과 확인
155
- final_results = [result for result in top_results if str(result) in last_paragraphs]
156
- if final_results:
157
- # 마지막 단락에서 가장 자주 등장한 결과
158
- final_counter = Counter([r for r in results if r in final_results])
159
- if final_counter:
160
- return final_counter.most_common(1)[0][0]
161
-
162
- # 수식과 함께 등장하는 결과 (예: "= 78", "총합: 78")
163
- for result in top_results:
164
- result_str = str(result)
165
- if re.search(r'=\s*' + result_str + r'(?!\d)', full_reasoning) or \
166
- re.search(r'결과[:는은이가]\s*' + result_str, full_reasoning) or \
167
- re.search(r'답[:는은이가]\s*' + result_str, full_reasoning) or \
168
- re.search(r'정답[:는은이가]\s*' + result_str, full_reasoning):
169
- return result
170
-
171
- # 위의 방법으로 결정할 수 없을 경우 가장 빈도가 높은 결과 반환
172
- return most_common[0][0]
173
-
174
- # 중간 결과를 요약하기 위한 프롬프트
175
- structured_reasoning_prompt = """
176
- 지금까지의 추론을 단계별로 정리해보겠습니다:
177
-
178
- 1. 문제 분석:
179
- - 주어진 정보: {given_info}
180
- - 구해야 할 것: {goal}
181
-
182
- 2. 계산 과정:
183
- {calculation_steps}
184
-
185
- 3. 현재까지의 결론:
186
- {current_conclusion}
187
-
188
- 이제 다음 단계로 진행하겠습니다.
189
- """
190
-
191
- # 최종 결과 검증을 위한 프롬프트
192
- verification_prompt = """
193
- 지금까지의 추론 과정에서 여러 결과가 도출되었습니다:
194
- {different_results}
195
-
196
- 이 중에서 가장 정확한 답변을 찾기 위해 계산 과정을 처음부터 다시 검토하겠습니다:
197
-
198
- 1. 문제 분석:
199
- - 주어진 정보: {given_info}
200
- - 구해야 할 것: {goal}
201
-
202
- 2. 단계별 계산 과정:
203
- {calculation_steps}
204
-
205
- 3. 결론:
206
- 위 계산 과정을 통해 정확한 답은 {result}입니다.
207
- """
208
-
209
  # 최종 답변 생성을 위한 프롬프트 추가
210
  final_answer_prompt = """
211
- 지금까지의 체계적인 추론 과정을 종합하여, 원래 질문에 답변하겠습니다:
212
-
213
  {question}
214
 
215
- 추론 과정을 검토한 결과, 다음과 같은 결론에 도달했습니다:
216
  {reasoning_conclusion}
217
 
218
- 따라서 최종 답변은:
219
  {ANSWER_MARKER}
220
  """
221
 
@@ -260,27 +83,6 @@ def rebuild_messages(history: list):
260
  return messages
261
 
262
 
263
- def extract_info_from_question(question):
264
- """문제에서 주어진 정보와 목표를 추출합니다."""
265
- # 기본 값
266
- given_info = "문제에서 제공된 모든 조건과 수치"
267
- goal = "문제에서 요구하는 값이나 결과"
268
-
269
- # 일반적인 정보 추출 패턴
270
- if "몇 개" in question or "개수" in question:
271
- goal = "특정 조건을 만족하는 항목의 개수"
272
- elif "얼마" in question:
273
- goal = "특정 값 또는 금액"
274
- elif "나이" in question:
275
- goal = "사람의 나이"
276
- elif "확률" in question:
277
- goal = "특정 사건의 확률"
278
- elif "평균" in question:
279
- goal = "값들의 평균"
280
-
281
- return given_info, goal
282
-
283
-
284
  @spaces.GPU
285
  def bot_original(
286
  history: list,
@@ -349,9 +151,6 @@ def bot_thinking(
349
 
350
  # 필요한 경우 추론에 질문을 다시 삽입하기 위함
351
  question = history[-1]["content"]
352
-
353
- # 문제에서 주어진 정보와 목표 추출
354
- given_info, goal = extract_info_from_question(question)
355
 
356
  # 보조자 메시지 준비
357
  history.append(
@@ -368,29 +167,10 @@ def bot_thinking(
368
  # 전체 추론 과정을 저장할 변수
369
  full_reasoning = ""
370
 
371
- # 추론 과정에서 수집된 계산 단계 저장
372
- calculation_steps = ""
373
- current_conclusion = "아직 최종 결론에 도달하지 않았습니다."
374
-
375
  # 추론 단계 실행
376
  for i, prepend in enumerate(rethink_prepends):
377
  if i > 0:
378
  messages[-1]["content"] += "\n\n"
379
-
380
- # 첫 단계에서 일반적인 추론 가이드 추가
381
- if i == 0:
382
- messages[-1]["content"] += general_reasoning_guide + "\n\n"
383
-
384
- # 중간 단계에서 구조화된 추론 요약 추가
385
- if i > 1 and calculation_steps:
386
- structured_summary = structured_reasoning_prompt.format(
387
- given_info=given_info,
388
- goal=goal,
389
- calculation_steps=calculation_steps,
390
- current_conclusion=current_conclusion
391
- )
392
- messages[-1]["content"] += structured_summary + "\n\n"
393
-
394
  messages[-1]["content"] += prepend.format(question=question)
395
 
396
  t = threading.Thread(
@@ -406,12 +186,7 @@ def bot_thinking(
406
  t.start()
407
 
408
  # 새 내용으로 히스토리 재구성
409
- if i == 0:
410
- history[-1].content += general_reasoning_guide + "\n\n"
411
- if i > 1 and calculation_steps:
412
- history[-1].content += structured_summary + "\n\n"
413
  history[-1].content += prepend.format(question=question)
414
-
415
  for token in streamer:
416
  history[-1].content += token
417
  history[-1].content = reformat_math(history[-1].content)
@@ -420,77 +195,13 @@ def bot_thinking(
420
 
421
  # 각 추론 단계의 결과를 full_reasoning에 저장
422
  full_reasoning = history[-1].content
423
-
424
- # 계산 단계 추출 및 업데이트
425
- new_content = history[-1].content.split(prepend.format(question=question))[-1]
426
- if "=" in new_content or ":" in new_content:
427
- # 계산 단계가 있는 것으로 간주
428
- calculation_steps += f"\n - {new_content.strip()}"
429
-
430
- # 단계에서 가능한 결론 추출
431
- results = extract_calculation_results(new_content)
432
- if results:
433
- current_conclusion = f"현재 계산된 값: {results[-1]}"
434
 
435
  # 추론 완료, 이제 최종 답변을 생성
436
  history[-1].metadata = {"title": "💭 사고 과정", "status": "done"}
437
 
438
- # 추론 과정에서 도출된 모든 결과 추출
439
- all_results = extract_calculation_results(full_reasoning)
440
-
441
- # 결과가 있는 경우 검증 단계 추가
442
- if all_results and len(set(all_results)) > 1:
443
- # 결과별 빈도 계산
444
- result_counter = Counter(all_results)
445
- different_results = "\n".join([f"{result} (빈도: {freq}회)" for result, freq in result_counter.most_common()])
446
-
447
- # 최적의 결과 결정
448
- best_result = determine_best_result(all_results, full_reasoning)
449
-
450
- # 모델에게 가장 정확한 결과 선택 요청
451
- verify_prompt = verification_prompt.format(
452
- different_results=different_results,
453
- given_info=given_info,
454
- goal=goal,
455
- calculation_steps=calculation_steps,
456
- result=best_result
457
- )
458
- messages[-1]["content"] += "\n\n" + verify_prompt
459
-
460
- # 검증 단계 실행
461
- t = threading.Thread(
462
- target=pipe,
463
- args=(messages,),
464
- kwargs=dict(
465
- max_new_tokens=max_num_tokens // 2,
466
- streamer=streamer,
467
- do_sample=False, # 확정적인 결과를 위해 샘플링 비활성화
468
- temperature=0.3, # 낮은 온도 사용
469
- ),
470
- )
471
- t.start()
472
-
473
- history[-1].content += "\n\n" + verify_prompt
474
- for token in streamer:
475
- history[-1].content += token
476
- history[-1].content = reformat_math(history[-1].content)
477
- yield history
478
- t.join()
479
-
480
- # 검증 단계 후 full_reasoning 업데이트
481
- full_reasoning = history[-1].content
482
-
483
- # 최종 결과 결정
484
- final_results = extract_calculation_results(full_reasoning)
485
- best_result = determine_best_result(final_results, full_reasoning) if final_results else None
486
-
487
- # 최종 결론 생성
488
- if best_result is not None:
489
- reasoning_conclusion = f"추론 과정을 종합한 결과, 정확한 답변은 {best_result}입니다."
490
- else:
491
- # 결과를 추출할 수 없는 경우의 대비책
492
- reasoning_parts = full_reasoning.split("\n\n")
493
- reasoning_conclusion = "\n\n".join(reasoning_parts[-2:]) if len(reasoning_parts) > 2 else full_reasoning
494
 
495
  # 최종 답변 메시지 추가
496
  history.append(gr.ChatMessage(role="assistant", content=""))
@@ -502,7 +213,7 @@ def bot_thinking(
502
  reasoning_conclusion=reasoning_conclusion,
503
  ANSWER_MARKER=ANSWER_MARKER
504
  )
505
- final_messages[-1]["content"] += "\n\n" + final_prompt
506
 
507
  # 최종 답변 생성
508
  t = threading.Thread(
@@ -512,7 +223,7 @@ def bot_thinking(
512
  max_new_tokens=final_num_tokens,
513
  streamer=streamer,
514
  do_sample=do_sample,
515
- temperature=temperature * 0.8, # 최종 답변에 더 확신을 주기 위해 온도 약간 낮춤
516
  ),
517
  )
518
  t.start()
@@ -566,10 +277,9 @@ with gr.Blocks(fill_height=True, title="Vidraft ThinkFlow") as demo:
566
  examples = gr.Examples(
567
  examples=[
568
  "[출처: MATH-500)] 처음 100개의 양�� 정수 중에서 3, 4, 5로 나누어 떨어지는 수는 몇 개입니까?",
569
- "[출처: MATH-500)] 잉크의 땅에서 돈 시스템은 독특합니다. 트링킛 1개는 블링킷 4개와 같고, 블링킷 3개는 드링크 7개와 같습니다. 트링킷에서 드링크 56개의 가치는 얼마입니까?",
570
  "[출처: MATH-500)] 에이미, 벤, 크리스의 평균 나이는 6살입니다. 4년 전 크리스는 지금 에이미와 같은 나이였습니다. 4년 후 벤의 나이는 그때 에이미의 나이의 $\\frac{3}{5}$가 될 것입니다. 크리스는 지금 몇 살입니까?",
571
- "[출처: MATH-500)] 노란색과 파란색 구슬이 들어 있는 가방이 있습니다. 현재 파란색 구슬과 노란색 구슬의 비율은 4:3입니다. 파란색 구슬 5개를 더하고 노란색 구슬 3개를 제거하면 비율은 7:3이 됩니다. 더 넣기 전에 가방에 파란색 구슬이 몇 개 있었습니까?",
572
- "수학 동아리에서 다가올 여행을 위한 기금 모금을 위해 베이킹 세일을 열고 있습니다. 3개에 54달러짜리 쿠키를 1달러에 판매하고, 20개에 컵케이크를 각각 2달러에 판매하고, 35개에 브라우니를 각각 1달러에 판매합니다. 수학 동아리에서 이 제품을 굽는 데 15달러가 들었다면, 수익은 얼마였을까요?"
573
  ],
574
  inputs=msg
575
  )
@@ -623,4 +333,4 @@ with gr.Blocks(fill_height=True, title="Vidraft ThinkFlow") as demo:
623
  )
624
 
625
  if __name__ == "__main__":
626
- demo.queue().launch() # title 매개변수 제거
 
1
  import re
2
  import threading
 
3
 
4
  import gradio as gr
5
  import spaces
 
7
  from transformers import pipeline
8
 
9
  # 모델과 토크나이저 로딩
10
+ model_name = "trillionlabs/Trillion-7B-preview"
11
  if gr.NO_RELOAD:
12
  pipe = pipeline(
13
  "text-generation",
 
23
  rethink_prepends = [
24
  "자, 이제 다음을 파악해야 합니다 ",
25
  "제 생각에는 ",
 
26
  "다음 사항이 맞는지 확인해 보겠습니다 ",
27
  "또한 기억해야 할 것은 ",
28
  "또 다른 주목할 점은 ",
 
30
  "이제 충분히 이해했다고 생각합니다 ",
31
  ]
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  # 최종 답변 생성을 위한 프롬프트 추가
34
  final_answer_prompt = """
35
+ 지금까지의 추론 과정을 바탕으로, 원래 질문에 사용된 언어로 답변하겠습니다:
 
36
  {question}
37
 
38
+ 아래는 내가 추론한 결론입니다:
39
  {reasoning_conclusion}
40
 
41
+ 추론을 기반으로 최종 답변:
42
  {ANSWER_MARKER}
43
  """
44
 
 
83
  return messages
84
 
85
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
  @spaces.GPU
87
  def bot_original(
88
  history: list,
 
151
 
152
  # 필요한 경우 추론에 질문을 다시 삽입하기 위함
153
  question = history[-1]["content"]
 
 
 
154
 
155
  # 보조자 메시지 준비
156
  history.append(
 
167
  # 전체 추론 과정을 저장할 변수
168
  full_reasoning = ""
169
 
 
 
 
 
170
  # 추론 단계 실행
171
  for i, prepend in enumerate(rethink_prepends):
172
  if i > 0:
173
  messages[-1]["content"] += "\n\n"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  messages[-1]["content"] += prepend.format(question=question)
175
 
176
  t = threading.Thread(
 
186
  t.start()
187
 
188
  # 새 내용으로 히스토리 재구성
 
 
 
 
189
  history[-1].content += prepend.format(question=question)
 
190
  for token in streamer:
191
  history[-1].content += token
192
  history[-1].content = reformat_math(history[-1].content)
 
195
 
196
  # 각 추론 단계의 결과를 full_reasoning에 저장
197
  full_reasoning = history[-1].content
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  # 추론 완료, 이제 최종 답변을 생성
200
  history[-1].metadata = {"title": "💭 사고 과정", "status": "done"}
201
 
202
+ # 추론 과정에서 결론 부분을 추출 (마지막 1-2 문단 정도)
203
+ reasoning_parts = full_reasoning.split("\n\n")
204
+ reasoning_conclusion = "\n\n".join(reasoning_parts[-2:]) if len(reasoning_parts) > 2 else full_reasoning
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
  # 최종 답변 메시지 추가
207
  history.append(gr.ChatMessage(role="assistant", content=""))
 
213
  reasoning_conclusion=reasoning_conclusion,
214
  ANSWER_MARKER=ANSWER_MARKER
215
  )
216
+ final_messages[-1]["content"] += final_prompt
217
 
218
  # 최종 답변 생성
219
  t = threading.Thread(
 
223
  max_new_tokens=final_num_tokens,
224
  streamer=streamer,
225
  do_sample=do_sample,
226
+ temperature=temperature,
227
  ),
228
  )
229
  t.start()
 
277
  examples = gr.Examples(
278
  examples=[
279
  "[출처: MATH-500)] 처음 100개의 양�� 정수 중에서 3, 4, 5로 나누어 떨어지는 수는 몇 개입니까?",
280
+ "[출처: MATH-500)] 잉크의 땅에서 돈 시스템은 독특합니다. 트링킷 1개는 블링킷 4개와 같고, 블링킷 3개는 드링크 7개와 같습니다. 트링킷에서 드링크 56개의 가치는 얼마입니까?",
281
  "[출처: MATH-500)] 에이미, 벤, 크리스의 평균 나이는 6살입니다. 4년 전 크리스는 지금 에이미와 같은 나이였습니다. 4년 후 벤의 나이는 그때 에이미의 나이의 $\\frac{3}{5}$가 될 것입니다. 크리스는 지금 몇 살입니까?",
282
+ "[출처: MATH-500)] 노란색과 파란색 구슬이 들어 있는 가방이 있습니다. 현재 파란색 구슬과 노란색 구슬의 비율은 4:3입니다. 파란색 구슬 5개를 더하고 노란색 구슬 3개를 제거하면 비율은 7:3이 됩니다. 더 넣기 전에 가방에 파란색 구슬이 몇 개 있었습니까?"
 
283
  ],
284
  inputs=msg
285
  )
 
333
  )
334
 
335
  if __name__ == "__main__":
336
+ demo.queue().launch()