"""
终端输出模块。
负责把演示过程打印得清晰易读,包括:
- 项目是否真实调用 API 的说明
- 各文件分工与运行流程
- 每道题三种模式的对比结果
"""
import sys
import textwrap
from config import API_KEY, MODEL_NAME, SEED, TEMPERATURE
ROLE_LABELS = {
"system": "system(系统角色:设定行为规则)",
"user": "user(用户角色:本次提问)",
"assistant": "assistant(助手角色:示例回答,供模型模仿)",
}
def _configure_stdout() -> None:
"""尽量让 Windows 终端正确显示中文。"""
if hasattr(sys.stdout, "reconfigure"):
try:
sys.stdout.reconfigure(encoding="utf-8")
except Exception:
pass
_configure_stdout()
def print_banner(title: str) -> None:
line = "=" * 60
print(f"\n{line}\n {title}\n{line}")
def print_section(title: str) -> None:
print(f"\n{'-' * 60}\n>> {title}\n{'-' * 60}")
def print_kv(label: str, value: str, indent: int = 0) -> None:
prefix = " " * indent
print(f"{prefix}{label}")
wrapped = textwrap.indent(textwrap.fill(value, width=72), " ")
print(wrapped)
def print_model_reply(reply: str) -> None:
print("\n【模型回复】")
print(textwrap.indent(reply, " "))
def print_messages(messages: list[dict[str, str]], summary: str = "") -> None:
"""打印本次发送给模型的完整 messages,便于对比三种模式的提示词差异。"""
print("\n【发送给模型的提示词】")
if summary:
print(f" 结构说明:{summary}")
print(f" 共 {len(messages)} 条消息:")
for i, msg in enumerate(messages, start=1):
role = msg["role"]
label = ROLE_LABELS.get(role, role)
content = msg["content"].strip()
print(f"\n --- 消息 {i} · {label} ---")
print(textwrap.indent(content, " "))
def _mask_api_key(key: str | None) -> str:
if not key:
return "未配置"
if len(key) <= 8:
return "已配置(长度较短,已隐藏)"
return f"已配置({key[:4]}...{key[-4:]})"
def print_runtime_info() -> None:
"""启动时打印运行环境与真实性说明。"""
print_section("运行环境(真实 API 调用,非模拟)")
print_kv("调用方式", "dashscope.Generation.call() → 阿里云百炼云端")
print_kv("模型", MODEL_NAME)
print_kv("API Key", _mask_api_key(API_KEY))
print_kv("参数", f"temperature={TEMPERATURE}, seed={SEED}")
print_kv(
"是否真实运行",
"是。每次「模型回复」都是实时请求百炼接口返回的结果,"
"会消耗 Token;断网或 Key 无效时会直接报错,没有写死的假答案。",
)
def print_project_structure() -> None:
"""打印项目构建方式,帮助学生理解代码分工。"""
print_section("项目是怎么构建的")
lines = [
"main.py 入口:组织演示流程,打印对比小结",
"demo.py 核心:三种模式组装 messages 并调用模型",
"prompts.py 提示词:无CoT / 零样本CoT / 少样本CoT 模板(改效果主要改这里)",
"questions.py 题库:3 道经典演示题",
"llm_client.py API层:唯一真正联网发请求的地方",
"config.py 配置:从 os.getenv 读取 DASHSCOPE_API_KEY",
]
for line in lines:
print(f" {line}")
def print_run_flow() -> None:
"""打印单道题的执行步骤。"""
print_section("单道题运行流程(每题调用 3 次百炼 API)")
steps = [
"1. main.py 从 questions.py 取出题目",
"2. 模式 A:prompts.py(无CoT) → demo.py 拼 messages → llm_client.py 发请求",
"3. 模式 B:prompts.py(零样本CoT) → demo.py 拼 messages → llm_client.py 发请求",
"4. 模式 C:prompts.py(少样本CoT+示例) → demo.py 拼 messages → llm_client.py 发请求",
"5. main.py 提取「最终答案」,判断正确性与是否有分步推理",
"6. 打印 A/B/C 对比小结",
]
for step in steps:
print(f" {step}")
def print_intro() -> None:
print_banner("CoT 思维链(Chain-of-Thought)教学演示")
print(
textwrap.fill(
"CoT 的核心:不要急着给最终答案,先让模型把中间推理步骤写出来。"
"这样复杂题更不容易跳步出错,推理过程也便于检查和纠错。",
width=72,
)
)
print("\n本演示对比三种写法:")
print(" 1) 无 CoT → 直接要答案(容易跳步)")
print(" 2) 零样本 CoT → 不给示例,只要求分步思考")
print(" 3) 少样本 CoT → 给一个带推理过程的示例,再让模型模仿")
print_runtime_info()
print_project_structure()
print_run_flow()
print("\n网页版演示:python web_app.py → http://127.0.0.1:8765")
print("详细说明见:docs/项目说明.md")