"""
CoT 思维链教学演示(终端版)
运行前准备:
1. pip install -r requirements.txt
2. 系统环境变量中已配置 DASHSCOPE_API_KEY(程序通过 os.getenv 读取)
运行方式:
python main.py # 默认演示第 1 道题
python main.py --all # 演示全部 3 道题
python main.py --only 2 # 只演示第 2 道题
python web_app.py # 启动网页版(推荐课堂演示)
或直接双击 run.bat / run_web.bat
"""
from __future__ import annotations
import argparse
import sys
from analysis import extract_final_answer, has_reasoning_steps, is_answer_correct
from display import (
print_banner,
print_intro,
print_kv,
print_messages,
print_model_reply,
print_section,
)
from llm_client import get_call_count
from questions import DEMO_QUESTIONS
from service import MODES, check_api_key, question_to_dict
def _configure_stdout() -> None:
if hasattr(sys.stdout, "reconfigure"):
try:
sys.stdout.reconfigure(encoding="utf-8")
except Exception:
pass
def run_one_question(index: int) -> None:
q = question_to_dict(index)
print_banner(f"题目 {index}:{q['title']}")
print_kv("题目", q["question"])
print_kv("参考答案", q["expected_answer"])
print_kv("为什么适合演示 CoT", q["why_hard"])
question = DEMO_QUESTIONS[index - 1]
results: list[tuple[str, object, str, bool, bool]] = []
for step, mode in enumerate(MODES, start=1):
mode_name = f"{mode.title} · {mode.subtitle}({mode.badge})"
print_section(mode_name)
result = mode.runner(question)
print_messages(result.messages, result.prompt_summary)
print(f"\n [步骤 {step}/3] 正在调用百炼 API...")
print(" 流程:上方提示词 → llm_client.py → 百炼 qwen-plus")
print_model_reply(result.reply)
final_answer = extract_final_answer(result.reply)
correct = is_answer_correct(final_answer, question.expected_answer)
stepped = has_reasoning_steps(result.reply)
print(f"\n 提取到的最终答案:{final_answer}")
print(f" 答案是否正确:{'正确' if correct else '错误'}")
print(f" 是否含分步推理:{'是' if stepped else '否'}")
results.append((mode_name, result, final_answer, correct, stepped))
print_section("本题对比小结")
print(" ┌─ 提示词差异 ─────────────────────────────────────────")
for mode_name, result, _, _, _ in results:
print(f" │ {mode_name}")
print(f" │ 消息条数:{len(result.messages)} 条 | {result.prompt_summary}")
print(" └──────────────────────────────────────────────────────")
print()
print(" ┌─ 结果对比 ─────────────────────────────────────────")
for mode_name, _, final_answer, correct, stepped in results:
print(f" │ {mode_name}")
print(f" │ 最终答案:{final_answer}({'正确' if correct else '错误'})")
print(f" │ 分步推理:{'有' if stepped else '无'}")
print(" └──────────────────────────────────────────────────────")
print(
"\n 课堂观察要点:\n"
" · 对比上方【发送给模型的提示词】:A 最短,B 多了分步要求,C 多了示例推理链;\n"
" · 无 CoT 往往只有一行答案,复杂题容易跳步;\n"
" · 零样本 CoT 会展开推理链,过程可审查;\n"
" · 少样本 CoT 会模仿示例格式,输出更稳定。"
)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="CoT 思维链 DashScope 教学演示")
group = parser.add_mutually_exclusive_group()
group.add_argument("--all", action="store_true", help="演示全部 3 道题")
group.add_argument(
"--only",
type=int,
choices=range(1, len(DEMO_QUESTIONS) + 1),
metavar="N",
help=f"只运行第 N 道题(1-{len(DEMO_QUESTIONS)}),默认 N=1",
)
return parser.parse_args()
def main() -> None:
_configure_stdout()
try:
check_api_key()
except RuntimeError as exc:
raise SystemExit(str(exc)) from exc
args = parse_args()
print_intro()
if args.all:
for idx in range(1, len(DEMO_QUESTIONS) + 1):
run_one_question(idx)
else:
run_one_question(args.only or 1)
print_banner("演示结束")
print(f"本次共发起 {get_call_count()} 次百炼 API 真实调用(每次调用均消耗 Token)。")
print("网页版演示:python web_app.py 或双击 run_web.bat")
print("详细项目说明见:docs/项目说明.md")
if __name__ == "__main__":
main()