
本文介绍如何将基于python的命令行式递进问答程序(如“5 whys” introspection工具)改造为可在浏览器中运行的web应用,使用flask框架实现前后端交互、状态管理与答案持久化。
本文介绍如何将基于python的命令行式递进问答程序(如“5 whys” introspection工具)改造为可在浏览器中运行的web应用,使用flask框架实现前后端交互、状态管理与答案持久化。
将一个面向终端的交互式自省程序(例如逐层追问目标与动因的“Why Chain”工具)迁移到浏览器环境,核心在于:用HTTP请求替代input()、用模板渲染替代控制台输出、用服务端状态管理替代局部变量,并引入基础的数据存储能力。以下是一个轻量、可运行、易扩展的实现方案。
✅ 技术选型说明
- 后端框架:Flask(Python)——轻量、学习成本低、适合快速原型;无需复杂配置即可处理表单提交与页面跳转。
- 前端模板:Jinja2(Flask内置)——支持动态插入问题文本、隐藏当前题号、条件渲染结束提示。
-
数据暂存:内存字典 + 文件写入(演示用);生产环境应替换为SQLite或PostgreSQL,并配合用户会话(
session)隔离不同用户数据。 - 不推荐纯前端方案(如仅用HTML+JS):无法安全保存用户答案(localStorage易丢失/被清除),且无法实现多用户登录与数据库持久化——这正是原问题明确提出的核心需求。
?️ 快速上手:三步搭建 Web 版自省问答
1. 安装依赖
pip install flask
2. 创建主程序 app.py
from flask import Flask, render_template, request, session
import os
app = Flask(__name__)
app.secret_key = "dev-key-for-session" # 生产环境请使用 secrets.token_hex()
# 问题定义(支持动态插值)
QUESTIONS = [
"What is your goal?",
"Why do you want {{ answer_1 }}?",
"Why do you want {{ answer_2 }}?",
"What would achieving this mean to you?"
]
@app.route("/", methods=["GET", "POST"])
def index():
if "answers" not in session:
session["answers"] = {}
session["current_step"] = 0
step = session["current_step"]
if request.method == "POST":
answer = request.form.get("answer", "").strip()
if not answer:
return render_template("questions.html",
question=QUESTIONS[step],
current_step=step,
error="Answer cannot be empty"
)
session["answers"][f"answer_{step + 1}"] = answer
session["current_step"] = step + 1
session.modified = True # 确保更新被保存
# 检查是否完成
if step >= len(QUESTIONS):
# ✅ 这里可接入真实数据库(如 SQLAlchemy + SQLite)
save_to_database(session["answers"])
session.clear() # 清理会话,准备下一轮
return render_template("thankyou.html")
# 渲染当前问题(支持模板变量替换)
question = QUESTIONS[step]
for i in range(1, step + 1):
key = f"answer_{i}"
if key in session["answers"]:
question = question.replace(f"{{{{ answer_{i} }}}}", session["answers"][key])
return render_template("questions.html",
question=question,
current_step=step,
total_steps=len(QUESTIONS),
error=None
)
def save_to_database(answers):
"""示例:将答案写入文件(生产环境请替换为数据库操作)"""
with open("user_answers.log", "a") as f:
f.write(f"\n--- Session at {os.popen('date').read().strip()} ---\n")
for k, v in answers.items():
f.write(f"{k}: {v}\n")
if __name__ == "__main__":
app.run(debug=True) # 开发模式;部署时禁用 debug
3. 创建模板 templates/questions.html
<meta charset="UTF-8"><title>深度自省问答</title><style>
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; max-width: 600px; margin: 40px auto; padding: 0 20px; }
.error { color: #d32f2f; margin: 8px 0; }
</style><h1>? 深度自省问答</h1>
{% if error %}
<div class="error">{{ error }}</div>
{% endif %}
当前进度:第 {{ current_step + 1 }} 题 / 共 {{ total_steps }} 题
同时创建 templates/thankyou.html:
<title>感谢参与</title><h1>✅ 问答已完成!</h1>
<p>你的思考已记录。如需重新开始,请刷新页面。</p>
<a href="/">← 再来一次</a>
⚠️ 关键注意事项
-
会话安全:示例中使用
session存储用户答案,依赖secret_key加密签名。生产环境必须设置强随机密钥(如secrets.token_urlsafe(32)),并考虑使用服务器端会话(如Flask-Session+ Redis)。 -
数据库升级路径:
- 初级:SQLite(单文件,零配置)→ 使用
sqlite3或SQLAlchemy。 - 中级:PostgreSQL/MySQL → 支持多用户、并发、权限控制。
- 用户系统:集成
Flask-Login实现注册/登录,将answers关联到user_id。
- 初级:SQLite(单文件,零配置)→ 使用
-
问题动态性:当前示例支持
{{ answer_X }}插值;如需更灵活逻辑(如分支跳转),可在QUESTIONS中定义函数或使用状态机引擎。 -
部署建议:本地测试用
flask run;上线推荐Gunicorn + Nginx(Linux)或Waitress(Windows),切勿在生产环境启用debug=True。
通过以上结构,你已获得一个可立即运行、清晰分层、易于扩展的 Web 化自省工具基座——它不再是脚本,而是一个真正服务于用户的轻量级 SaaS 应用雏形。











