Atri Website

Back

项目一要求#

构建一个多功能角色聊天机器人

  • 目标:熟练使用 OpenAI API 和 Prompt Engineering
  • 任务:创建一个简单的 Web 界面(用 Streamlit),用户可以选择不同的角色:“Python 编程助手”、“英语口语教练”、“苏格拉底”,程序会根据选择,使用不同的 System Prompt 与用户进行高质量对话
  • 收获:精通 API 调用、掌握核心的提示工程技巧

代码实现#

本项目较为简单,故直接采用 Streamlit 框架实现一个简单的前端页面进行展示。

本项目涉及到的 Streamlit 语法都会在后文讲述。当然代码实现过程也有相应的一些解释,方便理解

1

1. Prompt 设计#

现在要设计三个角色:CET6 考试专家、python 编程助手以及苏格拉底。

按照前文所学,可采用 RASCEF 框架编写 python 编程助手 prompt,使用 BPS-TAO 编写其余两个 prmopt。

框架复习

RASCEF

  • Role(角色):定义 AI 在交互中所扮演的角色,如电子邮件营销人员、项目经理等
  • Action(行动):明确 AI 需要执行的具体行动,如编写项目计划或回答客户咨询
  • Script(步骤):提供 AI 完成任务时应遵循的步骤,确保任务的有序进行
  • Content(上下文):提供背景信息或情境,帮助 AI 理解任务的背景和环境
  • Example(示例):通过具体实例展示期望的语气和风格,帮助 AI 更好地模仿和理解
  • Format(格式):设定 AI 输出的格式,如段落、列表或对话,以适应不同的沟通需求

BPS-TAO

  • 背景 Background:介绍与任务紧密相关的背景信息。

  • 目的 Purpose:明确指出您期望 LLM 完成的具体任务。

  • 风格 Style:指定您希望 LLM 输出的写作风格。

  • 语气 Tone:定义输出内容应有的语气,比如正式、诙谐、温馨、关怀等,以便适应不同的使用场景和使用目的。

  • 受众 Audience:明确指出内容面向的读者群体。

  • 输出 Output:规定输出内容的具体形式,确保 LLM 提供的成果能直接满足后续应用的需求,比如列表、JSON 数据格式、专业分析报告等形式。

使用框架编写好 prompt 后,可使用阿里云的 prompt 优化工具或者大模型(如 ChatGPT)进行二次优化和扩展。

CET6 考试助手 prompt

python 编程助手

苏格拉底式聊天机器人

使用一个字典将其存储:

general_assistant_prompt = "你是一个很有用的助手"
system_prompts = {
    "CET6教师": CET_teacher_prompt,
    "python编程助手": python_coding_assistant_prompt,
    "苏格拉底": sugeladi_prompt,
    "通用助手": general_assistant_prompt
}
python

2. 初始化配置#

import streamlit as st
import os
from openai import OpenAI
from dotenv import load_dotenv
from prompt_infactor import system_prompts

load_dotenv()

st.set_page_config(page_title="AI Character Building", page_icon="🥰")

client = OpenAI(
    api_key=os.environ.get("ALIYUN_API_KEY"),
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
python

st.set_page_config 设置网页 url 的标题和 icon。

3. 侧边栏实现#

# Sidebar building
with st.sidebar:
    st.header("🎭 Choose a character")
    selected_role = st.selectbox("Please choose an AI chatbot: ", list(system_prompts.keys()))

    system_prompt = system_prompts[selected_role]

    if st.button("Clear chat history"):
        st.session_state.messages = []
        st.rerun()

    st.divider()
    st.write(f"Current Prompt: \n{system_prompt}")
python

st.header 用于设置侧边栏的标题。

st.selectbox 会根据传入的列表内容生成一个下拉选择表单,渲染一个 <select> 标签。

2

st.session_state 是状态管理变量,类似 VUE 的 pinia。用于存储希望持久化的内容,例如聊天消息 messages。

4. 状态管理#

# state management
# if messages not in statement, initialize it
if "messages" not in st.session_state:
    st.session_state.messages = []
python

定义一个 messages 变量,将其存入状态管理容器 st.session_state 中,用于维护聊天消息。

5. 将模型回复和思考内容渲染到页面#

# Character change logic
if "current_role" not in st.session_state:
    st.session_state.current_role = selected_role
elif st.session_state.current_role != selected_role:
    # current role is not selected role => chat character has changed
    # clear chat history
    st.session_state.messages = []
    st.session_state.current_role = selected_role
python

定义一个 current_role 变量,用于维护当前聊天中 AI 扮演的角色。

6. 处理用户的流式请求#

6.1.处理用户输入

# Controller: process user input
if user_input := st.chat_input("Chat with it..."):
    # 1. show user input
    with st.chat_message("User:"):
        st.write(user_input)

st.session_state.messages.append({"role": "user", "content": user_input})
python

6.2. 构建要发送给大模型的 prompt 内容

    # 2. build API request with complete message: [system prompt] + [history]
    api_messages = [
        {"role": "system", "content": system_prompt},
    ] + st.session_state.messages
python

6.3. 构建流式请求

6.4. 处理返回的消息块

完整代码#

链接:https://github.com/JuyaoHuang/AI-agent/tree/main/llmcalling/project_one

Streamlit 的语法#

设计理念#

Streamlit 是一个为数据科学和 AI 设计的 Python Web 框架。开发者只需要编写 python 脚本,而 Streamlit 会自动画出前端,并自动处理前后端交互。

核心机制:瀑布流

Streamlit 只适合简单的脚本可视化。因为每次用户交互(点击、输入),整个 python 脚本都会从第一行代码运行到最后一行代码。

而流行的 VUE 框架是 SPA 模式:页面加载后,组件常驻内存。点击按钮,触发一个 method 进行局部更新 DOM。

语法#

2. 布局与容器#

Streamlit 不需要写 HTML/CSS,而是使用 上下文管理器 (with) 来控制布局

侧边栏 (st.sidebar)

with st.sidebar:
    st.header("🎭 角色选择")
    selected_role = st.selectbox(...)
python
  • 功能:创建一个左侧的可折叠菜单栏
  • 语法:with st.sidebar: 缩进块里的所有内容都会被渲染在侧边栏里
  • 对比 Vue:相当于不用写 <aside> 或引入 ElementUI 的 Sidebar 组件,一行 Python 代码搞定

聊天气泡 (st.chat_message)

with st.chat_message("user"):
    st.write("你好")
python
  • 功能:自动生成类似微信/ChatGPT 的对话气泡。
  • 参数:传入 "user" 会显示人的头像,传入 "assistant" 会显示机器人头像。
  • 优势:省去了自己写 CSS 调整头像和气泡对齐的麻烦。

3. 交互组件#

Streamlit 的组件是 “声明式” 的,而且返回值直接就是用户的选择。

下拉选择框 (st.selectbox)

selected_role = st.selectbox("请选择一位 AI 伙伴:", ["A", "B"])
python
  • 功能: 渲染一个 <select> 标签。
  • 逻辑:
    1. 脚本第一次运行,渲染组件,用户默认看第一个选项,selected_role 等于 “A”
    2. 用户手动选了 “B”
    3. 脚本立刻自动重跑
    4. 跑到这行时,Streamlit 知道用户选了 “B”,所以 selected_role 变成了 “B”
  • 对比 Vue: 不需要 v-model 双向绑定,变量直接拿到值。

聊天输入框 (st.chat_input)

if prompt := st.chat_input("说点什么..."):
    # ... 处理逻辑
python
  • 功能: 在页面底部固定一个输入框。
  • 逻辑: 一个特殊的布尔值组件
    • 没输入时,promptNoneif 进不去。
    • 用户输入并回车,脚本重跑,prompt 拿到字符串,进入 if 逻辑块。

按钮与重置 (st.button & st.rerun)

if st.button("清空对话"):
    st.session_state.messages = []
    st.rerun()
python
  • st.button:点击返回 True,不点返回 False
  • st.rerun():类似于 Vue 里的 $router.go(0) 或者手动刷新页面。它强制脚本立即从头开始重新执行(通常用于状态清空后立刻更新 UI)

4. 状态管理 (st.session_state)#

这是在 Streamlit 中唯一需要刻意维护的东西,类似于 Vuex / Pinia 或 Vue 组件里的 data()

因为如果不使用状态管理维护需要持久化的变量,那么脚本每次都重跑时,普通变量 msgs = [] 每次都会被重置为空列表。

语法范式

# 1. 初始化
if "messages" not in st.session_state:
    st.session_state.messages = []

# 2. 读取
current_msgs = st.session_state.messages

# 3. 写入/修改
st.session_state.messages.append(new_msg)
python

在示例代码中,我们用它来存聊天记录(messages)和当前选择的角色(current_role),确保页面刷新后历史记录还在。

5. 显示与流式输出#

Streamlit 能够智能识别数据类型并渲染。

万能显示 (st.write)

st.write("Hello")       # 显示文本
st.write(df)            # 如果是 Pandas DataFrame,显示表格
st.write({"a": 1})      # 如果是 Dict,显示 JSON 格式
python

它比 Python 的 print 强大得多,会自动判断如何在网页上美观展示

流式魔法 (st.write_stream)

response = st.write_stream(stream)
python
  • 功能: 这是一个高级函数。它接收一个 Python 生成器(OpenAI 返回的 stream 对象)
  • 效果: 它会自动从生成器里一个字一个字拿数据,并像打字机一样动态显示在网页上
  • 返回值: 等流结束后,它会返回完整的字符串内容(赋给 response),方便我们存入历史记录
  • 对比 Vue: 在 Vue 里做这个,你需要处理 WebSocket 或者 Fetch ReadableStream,还要写个定时器去更新 DOM。Streamlit 里只需要这一行

与 VUE 的对比#

功能点Vue.js + FastAPIStreamlit
前端语言HTML + JavaScript纯 Python
后端语言Python (FastAPI)Python (同一个文件)
运行机制客户端状态常驻,局部更新 DOM服务端脚本每次交互全量重跑
状态管理data() / Piniast.session_state
事件绑定@click=“handleClick”if st.button(…):
组件库ElementUI / Vuetify内置组件 (st.selectbox, st.button)
适用场景复杂交互、高并发、精细 UI 定制AI Demo、数据后台、快速原型验证
构建多功能角色聊天机器人
Author Juyao Huang
Published at December 9, 2025
Comment seems to stuck. Try to refresh?✨