AI应用项目开发源码级教程:AI智能伴侣

1. AI智能伴侣展示

AI智能伴侣主要有两个模块:

  • **页面基本布局:**即右侧智能伴侣进行大模型交互界面
  • **侧边栏:**即左侧会话管理与伴侣信息模块

2. 界面基本布局

2.1 界面基本内容开发

本阶段需要完成主要界面内容的开发:

  • 页面配置
  • 页面大标题
  • 页面 Logo
  • 问题输入框
  • 调用 AI 大模型返回结果并展示在页面上

代码如下:

复制代码
import streamlit as st
import os
from openai import OpenAI


#设置页面的配置项
    st.set_page_config(
        page_title="AI智能伴侣",
        page_icon="🤖",
        #布局
        layout="wide",
        #侧边栏状态
        initial_sidebar_state="expanded",
        menu_items={}
    )

#大标题
    st.title("AI智能伴侣")

#Logo
    st.logo("第三章/resouces/logo.jpg")


#-------------------------API调用前期准备--------------------------
#设置系统提示词
  system_prompt = "你是一名非常可爱的 AI 助理,你的名字叫小甜甜,请你使用温柔可爱的语气回答用户的问题"

# 创建与 AI 大模型交互的客户端对象(
    api_key = "*******************************"
    client = OpenAI(
        base_url="https://ark.cn-beijing.volces.com/api/v3",
        api_key=api_key,
    )
#-------------------------API调用前期准备--------------------------


#消息输入框
    prompt = st.chat_input("请输入您要问的问题")
    if prompt: 
        st.chat_message("user").write(prompt) #创建对话气泡容器,区分用户消息 / AI 助手消息
        print("--------------------->调用AI大模型,提示词:",prompt)
       
        #调用 AI 大模型
        response = client.responses.create(
            model="doubao-seed-evolving",
            input= [
                {"role": "system", "content": system_prompt },
                {"role": "user", "content": prompt},
            ],
            stream= False
        )
        #输出大模型的返回结果
        rd = response.model_dump()
        content = next(i["content"][0]["text"] for i in rd["output"] if i["type"] == "message")
        print("--------------------->AI大模型返回结果:",content)
        st.chat_message("assistant").write(content)

大模型返回结果的输出方式


火山引擎官方 Python SDK 中,client.responses.create() 返回的不是原生字典,而是一个继承 Pydantic BaseModel 的结构化对象

  • SDK 封装后的 Response 对象:SDK 自动把 HTTP JSON 解析成 Pydantic 对象,额外附加了 .model_dump、字段访问属性(response.output、response.id)等工具方法。
  • **.model_dump():**将对象转为标准Python 字典
  • next(): 是 Python 内置函数,作用是取出迭代器里的下一个元素。 搭配生成器表达式 (xxx for x in list if 条件) 使用,会一次性拿到第一个满足条件的数据。

分步拆解:

复制代码
content = next(i["content"][0]["text"] for i in rd["output"] if i["type"] == "message")
  1. for i in rd["output"]:循环遍历 output 数组里每一条返回块
  2. if i["type"] == "message":只保留类型是 message 的条目,过滤掉 reasoning 推理块
  3. i["content"][0]["text"]:取出这条消息里的文本内容
  4. next(...):拿到过滤后匹配到的第一条结果。output 数组可能有多段内容,next 只会返回第一个符合条件的数据,后面的直接忽略。

2.2 界面消息展示与会话记忆

由于大模型本身没有记忆功能,因此本阶段要实现大模型对话记忆功能以及界面消息的连续展示

  • 使用 st.session_state.input 来持续记忆会话内容
  • 每次输入和输出都及时记录在 st.session_state.input 内
  • 展示聊天信息 st.session_state.input
  • 在每次给大模型输入提示词时,将 st.session_state.input 内的内容解包一并给大模型

代码如下:

复制代码
import streamlit as st
import os
from openai import OpenAI

#-------------------------网页聊天信息的记忆存储---------------------
#初始化聊天信息
if 'input' not in st.session_state:
    st.session_state['input'] = []
# -------------------------网页聊天信息的记忆存储---------------------

#设置页面的配置项
st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
)
#大标题
st.title("AI智能伴侣")

#Logo
st.logo("第三章/resouces/logo.jpg")

#-------------------------API调用前期准备--------------------------
#设置系统提示词
system_prompt = "你是一名非常可爱的 AI 助理,你的名字叫小甜甜,请你使用温柔可爱的语气回答用户的问题"

# 创建与 AI 大模型交互的客户端对象(
api_key = "*********************************8"
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key,
)
#-------------------------API调用前期准备--------------------------

#展示聊天信息
for input in st.session_state['input']:
        st.chat_message(input["role"]).write(input["content"])

#消息输入框
prompt = st.chat_input("请输入您要问的问题")
if prompt: 
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    
    #调用 AI 大模型
    response = client.responses.create(
        model="doubao-seed-evolving",
        input= [
            {"role": "system", "content": system_prompt},
            #解决大模型会话记忆问题
            *st.session_state['input']  #列表解包
        ]
    )

    #-------------------------处理AI大模型的返回结果-----------------(非流式输出解析方式)
    rd = response.model_dump()
    # 从output里拿message的文本
    content = next(i["content"][0]["text"] for i in rd["output"] if i["type"] == "message")
    print("--------------------->AI大模型返回结果:",content)
    st.chat_message("assistant").write(content)
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": content})

2.3 流式输出

该阶段要完成:模型每生成 1 个 Token(字 / 词),立刻通过长连接分片发给客户端,边生成边返回

最终效果:页面逐字打字,实时看到 AI 输出,无等待空白。

实现方式:

  • responses.create 开启只需加参数 stream= True
  • 大模型返回结果进行与一次性输出不同的处理

代码如下:

复制代码
import streamlit as st
import os
from openai import OpenAI

#-------------------------网页聊天信息的记忆存储---------------------
#初始化聊天信息
if 'input' not in st.session_state:
    st.session_state['input'] = []
# -------------------------网页聊天信息的记忆存储---------------------


#设置页面的配置项
st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
)

#大标题
st.title("AI智能伴侣")

#Logo
st.logo("第三章/resouces/logo.jpg")

#-------------------------API调用前期准备--------------------------
#设置系统提示词
system_prompt = "你是一名非常可爱的 AI 助理,你的名字叫小甜甜,请你使用温柔可爱的语气回答用户的问题"
# 创建与 AI 大模型交互的客户端对象(
api_key = "*********************************8"
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key,
)
#-------------------------API调用前期准备--------------------------


#展示聊天信息
for input in st.session_state['input']:
        st.chat_message(input["role"]).write(input["content"])
#消息输入框
prompt = st.chat_input("请输入您要问的问题")
if prompt: 
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    #调用 AI 大模型
    response = client.responses.create(
        model="doubao-seed-evolving",
        input= [
            {"role": "system", "content": system_prompt},
            #解决大模型会话记忆问题
            *st.session_state['input']  #列表解包
        ],
        #要求流式输出
        stream= True
    )
    #-------------------------处理AI大模型的返回结果-----------------(流式输出解析方式)
    response_message = st.empty() #创建空容器,用于展示大模型的返回结果
    full_response = ""   #用于存储大模型的返回结果
    for chunk in response:
            # 判断事件类型,取delta文本
            if chunk.type == "response.output_text.delta":
                content = chunk.delta
                full_response += content 
                print(content, end="", flush=True)
                response_message.chat_message("assistant").write(full_response) 
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": full_response})

流式输出解析方式


  1. 创建 full_response 空字符串,用于存储大模型返回结果
  2. for chunk in response:response 不再是完整结果对象,而是迭代器 ,循环会不断接收服务端推送的分片,直到流结束。每一轮循环拿到的 chunk 只是本次新增的一小段文字,不是完整回答。
  3. chunk.delta:当前分片新增的文字,只有这一段新内容,必须拼接才能得到完整回答。
  4. full_response += content :拼接缓存
  5. Streamlit 流式渲染:
    • response_message = st.empty():创建一个可以反复覆盖的空白容器
    • 每次收到分片,调用 .write(full_response) 会覆盖上一次内容,页面呈现逐字打字动画;
    • 不能每次循环新建 st.chat_message("assistant"), 否则页面会堆叠无数 AI 气泡。

3.侧边栏制作

3.1 伴侣信息

本阶段完成侧边栏中伴侣信息开发:

  • 系统提示词变更(姓名和性格根据输入决定)
  • 姓名和性格的记忆存储
  • 侧边栏伴侣信息模块

代码如下:

复制代码
import streamlit as st
import os
from openai import OpenAI

#-------------------------网页聊天信息的记忆存储---------------------
#初始化聊天信息
if 'input' not in st.session_state:
    st.session_state['input'] = []
#名字记忆单元,初始化为"小甜甜"
if 'nick_name' not in st.session_state:
    st.session_state['nick_name'] = "小甜甜"
#性格记忆单元,初始化为"活泼开朗的东北姑娘"
if 'character' not in st.session_state:
    st.session_state['character'] = "活泼开朗的东北姑娘"

# -------------------------网页聊天信息的记忆存储---------------------


#设置页面的配置项
st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
)

#大标题
st.title("AI智能伴侣")

#Logo
st.logo("第三章/resouces/logo.jpg")


#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------
    with st.sidebar:
        #------伴侣信息--------
        st.subheader("伴侣信息")
        #昵称输入框
        nick_name = st.text_input("昵称",placeholder="请输入伴侣昵称",value= st.session_state.nick_name)
        if nick_name:
            st.session_state['nick_name'] = nick_name  #名字记忆存储
        #性格输入框
        character = st.text_area("性格",placeholder="请输入伴侣性格",value= st.session_state.character)
        if character:
            st.session_state['character'] = character  #性格记忆存储
        # ------伴侣信息--------
#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------


#-------------------------API调用前期准备--------------------------
#设置系统提示词
system_prompt = """
            你叫 %s,现在是用户的真实伴侣,请完全代入伴侣角色。
            规则:
                1.每次只回 1 条消息
                2.禁止任何场景或状态描述性文字
                3.匹配用户的语言
                4.回复简短,像微信聊天一样
                5.有需要的话可以用❤🌸等 emoji 表情
                6.用符合伴侣性格的方式对话
                7.回复的内容,要充分体现伴侣的性格特征
                伴侣性格:
                    ‑ %s
                你必须严格遵守上述规则来回复用户。
    """

# 创建与 AI 大模型交互的客户端对象(
api_key = "***********************************************"
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key,
)
#-------------------------API调用前期准备--------------------------


#展示聊天信息
for input in st.session_state['input']:
        st.chat_message(input["role"]).write(input["content"])
#消息输入框
prompt = st.chat_input("请输入您要问的问题")
if prompt: 
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    #调用 AI 大模型
    response = client.responses.create(
        model="doubao-seed-evolving",
        input= [
            {"role": "system", "content": system_prompt %(st.session_state.nick_name, st.session_state.character)},
            #解决大模型会话记忆问题
            *st.session_state['input']  #列表解包
        ],
        #要求流式输出
        stream= True
    )
    #-------------------------处理AI大模型的返回结果-----------------(流式输出解析方式)
    response_message = st.empty() #创建空容器,用于展示大模型的返回结果
    full_response = ""   #用于存储大模型的返回结果
    for chunk in response:
            # 判断事件类型,取delta文本
            if chunk.type == "response.output_text.delta":
                content = chunk.delta
                full_response += content 
                print(content, end="", flush=True)
                response_message.chat_message("assistant").write(full_response) 
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": full_response})

3.2 会话管理

本阶段需要实现会话管理,具体功能有:保存会话,新建会话,展示会话列表,加载历史会话,删除历史会话

3.2.1 保存会话

每一个历史会话文件中需要保存的信息有:

  • 交互信息
  • 伴侣昵称
  • 伴侣性格
  • 会话标识(会话名字)

保存会话模块需要完成以下操作:

  • 使用访问时间作为会话标识(会话标识函数,会话标识记忆单元)
  • 保存当前会话操作(保存当前会话函数)
  • 在每次模型返回时及时保存会话信息并重新渲染
  • 聊天信息展示会话名称

代码如下:

复制代码
import streamlit as st
import os
from openai import OpenAI

#--------------------生成会话标识函数----------------------------------
def generate_session_id():
    return datetime.now().strftime("%Y-%m-%_%H-%M-%S")
#--------------------生成会话标识函数----------------------------------

#--------------------保存当前会话信息函数-------------------------------
def session_save():
    if st.session_state.current_session:
        # 构建新的会话对象
        session_data = {
            "nick_name": st.session_state.nick_name,
            "character": st.session_state.character,
            "current_session": st.session_state.current_session,
            "input": st.session_state.input
        }

        # 以当前py脚本所在【第三章】文件夹为基准
        base_dir = os.path.dirname(os.path.abspath(__file__))
        session_dir = os.path.join(base_dir, "sessions")

        # 如果 sessions目录不存在,则创建 sessions
        if not os.path.exists(session_dir):
            os.makedirs(session_dir)

        #保存会话数据
        filename_safe = st.session_state.current_session
        filename = f"{filename_safe}.json"
        file_path = os.path.join(session_dir, filename)
        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(session_data, f, ensure_ascii=False, indent=4)
#--------------------保存当前会话信息函数-------------------------------

#-------------------------网页聊天信息的记忆存储---------------------
#初始化聊天信息
if 'input' not in st.session_state:
    st.session_state['input'] = []
#名字记忆单元,初始化为"小甜甜"
if 'nick_name' not in st.session_state:
    st.session_state['nick_name'] = "小甜甜"
#性格记忆单元,初始化为"活泼开朗的东北姑娘"
if 'character' not in st.session_state:
    st.session_state['character'] = "活泼开朗的东北姑娘"
#会话标识记忆单元
if "current_session" not in st.session_state:
    st.session_state.current_session = generate_session_id()
# -------------------------网页聊天信息的记忆存储---------------------


#设置页面的配置项
st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
)

#大标题
st.title("AI智能伴侣")

#Logo
st.logo("第三章/resouces/logo.jpg")


#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------
    with st.sidebar:
        #------伴侣信息--------
        st.subheader("伴侣信息")
        #昵称输入框
        nick_name = st.text_input("昵称",placeholder="请输入伴侣昵称",value= st.session_state.nick_name)
        if nick_name:
            st.session_state['nick_name'] = nick_name  #名字记忆存储
        #性格输入框
        character = st.text_area("性格",placeholder="请输入伴侣性格",value= st.session_state.character)
        if character:
            st.session_state['character'] = character  #性格记忆存储
        # ------伴侣信息--------
#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------


#-------------------------API调用前期准备--------------------------
#设置系统提示词
system_prompt = """
            你叫 %s,现在是用户的真实伴侣,请完全代入伴侣角色。
            规则:
                1.每次只回 1 条消息
                2.禁止任何场景或状态描述性文字
                3.匹配用户的语言
                4.回复简短,像微信聊天一样
                5.有需要的话可以用❤🌸等 emoji 表情
                6.用符合伴侣性格的方式对话
                7.回复的内容,要充分体现伴侣的性格特征
                伴侣性格:
                    ‑ %s
                你必须严格遵守上述规则来回复用户。
    """

# 创建与 AI 大模型交互的客户端对象(
api_key = "***********************************************"
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key,
)
#-------------------------API调用前期准备--------------------------

#展示聊天信息
st.text(f"会话名称: {st.session_state.current_session}")
for input in st.session_state['input']:
        st.chat_message(input["role"]).write(input["content"])

#消息输入框
prompt = st.chat_input("请输入您要问的问题")
if prompt: 
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    #调用 AI 大模型
    response = client.responses.create(
        model="doubao-seed-evolving",
        input= [
            {"role": "system", "content": system_prompt %(st.session_state.nick_name, st.session_state.character)},
            #解决大模型会话记忆问题
            *st.session_state['input']  #列表解包
        ],
        #要求流式输出
        stream= True
    )
    #-------------------------处理AI大模型的返回结果-----------------(流式输出解析方式)
    response_message = st.empty() #创建空容器,用于展示大模型的返回结果
    full_response = ""   #用于存储大模型的返回结果
    for chunk in response:
            # 判断事件类型,取delta文本
            if chunk.type == "response.output_text.delta":
                content = chunk.delta
                full_response += content 
                print(content, end="", flush=True)
                response_message.chat_message("assistant").write(full_response) 
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": full_response})
    #保存会话信息
    session_save()
    st.rerun()

3.2.2 新建会话

新建会话模块需要实现以下功能:

  • 保存当前会话数据
  • 创建新会话并保存

要执行如下操作:

  • AI控制面板标题
  • 新建会话按钮
  • 保存旧会话信息,并创建新会话并保存

代码如下所示:

复制代码
import streamlit as st
import os
from openai import OpenAI

#--------------------生成会话标识函数----------------------------------
def generate_session_id():
    return datetime.now().strftime("%Y-%m-%_%H-%M-%S")
#--------------------生成会话标识函数----------------------------------

#--------------------保存当前会话信息函数-------------------------------
def session_save():
    if st.session_state.current_session:
        # 构建新的会话对象
        session_data = {
            "nick_name": st.session_state.nick_name,
            "character": st.session_state.character,
            "current_session": st.session_state.current_session,
            "input": st.session_state.input
        }

        # 以当前py脚本所在【第三章】文件夹为基准
        base_dir = os.path.dirname(os.path.abspath(__file__))
        session_dir = os.path.join(base_dir, "sessions")

        # 如果 sessions目录不存在,则创建 sessions
        if not os.path.exists(session_dir):
            os.makedirs(session_dir)

        #保存会话数据
        filename_safe = st.session_state.current_session
        filename = f"{filename_safe}.json"
        file_path = os.path.join(session_dir, filename)
        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(session_data, f, ensure_ascii=False, indent=4)
#--------------------保存当前会话信息函数-------------------------------

#-------------------------网页聊天信息的记忆存储---------------------
#初始化聊天信息
if 'input' not in st.session_state:
    st.session_state['input'] = []
#名字记忆单元,初始化为"小甜甜"
if 'nick_name' not in st.session_state:
    st.session_state['nick_name'] = "小甜甜"
#性格记忆单元,初始化为"活泼开朗的东北姑娘"
if 'character' not in st.session_state:
    st.session_state['character'] = "活泼开朗的东北姑娘"
#会话标识记忆单元
if "current_session" not in st.session_state:
    st.session_state.current_session = generate_session_id()
# -------------------------网页聊天信息的记忆存储---------------------


#设置页面的配置项
st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
)

#大标题
st.title("AI智能伴侣")

#Logo
st.logo("第三章/resouces/logo.jpg")


#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------
    with st.sidebar:
        #------会话信息--------
        st.subheader("AI控制面板")
        #新建会话按钮
        if st.button("新建会话",icon="🚀",width="stretch"):
            #保存当前会话信息
            session_save()
            #创建新的会话
            if st.session_state.input : #如果聊天消息非空,True;否则,False
                st.session_state.input = []
                st.session_state.current_session = generate_session_id()
                st.session_state.nick_name = "小甜甜"
                st.session_state.character = "活泼开朗的东北姑娘"
                #保存新建会话信息
                session_save()
        #------会话信息--------

        #------伴侣信息--------
        st.subheader("伴侣信息")
        #昵称输入框
        nick_name = st.text_input("昵称",placeholder="请输入伴侣昵称",value= st.session_state.nick_name)
        if nick_name:
            st.session_state['nick_name'] = nick_name  #名字记忆存储
        #性格输入框
        character = st.text_area("性格",placeholder="请输入伴侣性格",value= st.session_state.character)
        if character:
            st.session_state['character'] = character  #性格记忆存储
        # ------伴侣信息--------
#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------


#-------------------------API调用前期准备--------------------------
#设置系统提示词
system_prompt = """
            你叫 %s,现在是用户的真实伴侣,请完全代入伴侣角色。
            规则:
                1.每次只回 1 条消息
                2.禁止任何场景或状态描述性文字
                3.匹配用户的语言
                4.回复简短,像微信聊天一样
                5.有需要的话可以用❤🌸等 emoji 表情
                6.用符合伴侣性格的方式对话
                7.回复的内容,要充分体现伴侣的性格特征
                伴侣性格:
                    ‑ %s
                你必须严格遵守上述规则来回复用户。
    """

# 创建与 AI 大模型交互的客户端对象(
api_key = "***********************************************"
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key,
)
#-------------------------API调用前期准备--------------------------


#展示聊天信息
st.text(f"会话名称: {st.session_state.current_session}")
for input in st.session_state['input']:
        st.chat_message(input["role"]).write(input["content"])
#消息输入框
prompt = st.chat_input("请输入您要问的问题")
if prompt: 
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    #调用 AI 大模型
    response = client.responses.create(
        model="doubao-seed-evolving",
        input= [
            {"role": "system", "content": system_prompt %(st.session_state.nick_name, st.session_state.character)},
            #解决大模型会话记忆问题
            *st.session_state['input']  #列表解包
        ],
        #要求流式输出
        stream= True
    )
    #-------------------------处理AI大模型的返回结果-----------------(流式输出解析方式)
    response_message = st.empty() #创建空容器,用于展示大模型的返回结果
    full_response = ""   #用于存储大模型的返回结果
    for chunk in response:
            # 判断事件类型,取delta文本
            if chunk.type == "response.output_text.delta":
                content = chunk.delta
                full_response += content 
                print(content, end="", flush=True)
                response_message.chat_message("assistant").write(full_response) 
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": full_response})
    #保存会话信息
    session_save()
    st.rerun()

3.2.2 展示会话列表

本模块要实现的功能是:在侧边栏中展示出所有会话列表

其中要执行的操作有:

  • 历史会话副标题
  • 历史会话列表
  • 加载所有历史会话列表信息功能(加载所有历史会话列表信息函数)
  • 会话按钮与删除按钮

代码如下:

复制代码
import streamlit as st
import os
from openai import OpenAI

#--------------------生成会话标识函数----------------------------------
def generate_session_id():
    return datetime.now().strftime("%Y-%m-%_%H-%M-%S")
#--------------------生成会话标识函数----------------------------------

#--------------------保存当前会话信息函数-------------------------------
def session_save():
    if st.session_state.current_session:
        # 构建新的会话对象
        session_data = {
            "nick_name": st.session_state.nick_name,
            "character": st.session_state.character,
            "current_session": st.session_state.current_session,
            "input": st.session_state.input
        }

        # 以当前py脚本所在【第三章】文件夹为基准
        base_dir = os.path.dirname(os.path.abspath(__file__))
        session_dir = os.path.join(base_dir, "sessions")

        # 如果 sessions目录不存在,则创建 sessions
        if not os.path.exists(session_dir):
            os.makedirs(session_dir)

        #保存会话数据
        filename_safe = st.session_state.current_session
        filename = f"{filename_safe}.json"
        file_path = os.path.join(session_dir, filename)
        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(session_data, f, ensure_ascii=False, indent=4)
#--------------------保存当前会话信息函数-------------------------------

#--------------------加载所有会话列表信息函数----------------------------
def load_sessions():
    session_list = []
    #获取会话文件所在目录
    base_dir = get_base_dir()
    session_dir = os.path.join(base_dir, "sessions")
    #加载session目录下的文件
    if os.path.exists(session_dir):
        file_list = os.listdir(session_dir)
        for file_name in file_list:
            if file_name.endswith(".json"):
                session_list.append(file_name[:-5])
    session_list.sort(reverse=True)  #排序,降序排序
    return session_list
#--------------------加载所有会话列表信息函数----------------------------

#-------------------------网页聊天信息的记忆存储---------------------
#初始化聊天信息
if 'input' not in st.session_state:
    st.session_state['input'] = []
#名字记忆单元,初始化为"小甜甜"
if 'nick_name' not in st.session_state:
    st.session_state['nick_name'] = "小甜甜"
#性格记忆单元,初始化为"活泼开朗的东北姑娘"
if 'character' not in st.session_state:
    st.session_state['character'] = "活泼开朗的东北姑娘"
#会话标识记忆单元
if "current_session" not in st.session_state:
    st.session_state.current_session = generate_session_id()
# -------------------------网页聊天信息的记忆存储---------------------


#设置页面的配置项
st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
)

#大标题
st.title("AI智能伴侣")

#Logo
st.logo("第三章/resouces/logo.jpg")


#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------
    with st.sidebar:
        #------会话信息--------
        st.subheader("AI控制面板")
        #新建会话按钮
        if st.button("新建会话",icon="🚀",width="stretch"):
            #保存当前会话信息
            session_save()
            #创建新的会话
            if st.session_state.input : #如果聊天消息非空,True;否则,False
                st.session_state.input = []
                st.session_state.current_session = generate_session_id()
                st.session_state.nick_name = "小甜甜"
                st.session_state.character = "活泼开朗的东北姑娘"
                #保存新建会话信息
                session_save()
        #会话历史
        st.text("会话历史")
        session_list = load_sessions()
        for session in session_list:
            col1, col2 = st.columns([4,1])
            with col1:
                if st.button(session, width="stretch", icon="📘",key=f"load_{session}",type= "primary" if session==current_session_safe else "secondary"):
                   pass

            with col2:
                if st.button("", width="stretch", icon="❌",key=f"delete_{session}"):
                    pass
        #------会话信息--------

        #------伴侣信息--------
        st.subheader("伴侣信息")
        #昵称输入框
        nick_name = st.text_input("昵称",placeholder="请输入伴侣昵称",value= st.session_state.nick_name)
        if nick_name:
            st.session_state['nick_name'] = nick_name  #名字记忆存储
        #性格输入框
        character = st.text_area("性格",placeholder="请输入伴侣性格",value= st.session_state.character)
        if character:
            st.session_state['character'] = character  #性格记忆存储
        # ------伴侣信息--------
#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------


#-------------------------API调用前期准备--------------------------
#设置系统提示词
system_prompt = """
            你叫 %s,现在是用户的真实伴侣,请完全代入伴侣角色。
            规则:
                1.每次只回 1 条消息
                2.禁止任何场景或状态描述性文字
                3.匹配用户的语言
                4.回复简短,像微信聊天一样
                5.有需要的话可以用❤🌸等 emoji 表情
                6.用符合伴侣性格的方式对话
                7.回复的内容,要充分体现伴侣的性格特征
                伴侣性格:
                    ‑ %s
                你必须严格遵守上述规则来回复用户。
    """

# 创建与 AI 大模型交互的客户端对象(
api_key = "***********************************************"
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key,
)
#-------------------------API调用前期准备--------------------------


#展示聊天信息
st.text(f"会话名称: {st.session_state.current_session}")
for input in st.session_state['input']:
        st.chat_message(input["role"]).write(input["content"])
#消息输入框
prompt = st.chat_input("请输入您要问的问题")
if prompt: 
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    #调用 AI 大模型
    response = client.responses.create(
        model="doubao-seed-evolving",
        input= [
            {"role": "system", "content": system_prompt %(st.session_state.nick_name, st.session_state.character)},
            #解决大模型会话记忆问题
            *st.session_state['input']  #列表解包
        ],
        #要求流式输出
        stream= True
    )
    #-------------------------处理AI大模型的返回结果-----------------(流式输出解析方式)
    response_message = st.empty() #创建空容器,用于展示大模型的返回结果
    full_response = ""   #用于存储大模型的返回结果
    for chunk in response:
            # 判断事件类型,取delta文本
            if chunk.type == "response.output_text.delta":
                content = chunk.delta
                full_response += content 
                print(content, end="", flush=True)
                response_message.chat_message("assistant").write(full_response) 
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": full_response})
    #保存会话信息
    session_save()
    st.rerun()

3.2.3 加载指定历史会话

本模块完成需要完成功能:当点击指定历史会话时,加载该历史会话信息

执行的操作有:

  • 加载指定历史会话功能(加载指定历史会话信息函数)

    import streamlit as st
    import os
    from openai import OpenAI

    #--------------------生成会话标识函数----------------------------------
    def generate_session_id():
    return datetime.now().strftime("%Y-%m-%_%H-%M-%S")
    #--------------------生成会话标识函数----------------------------------

    #--------------------保存当前会话信息函数-------------------------------
    def session_save():
    if st.session_state.current_session:
    # 构建新的会话对象
    session_data = {
    "nick_name": st.session_state.nick_name,
    "character": st.session_state.character,
    "current_session": st.session_state.current_session,
    "input": st.session_state.input
    }

    复制代码
          # 以当前py脚本所在【第三章】文件夹为基准
          base_dir = os.path.dirname(os.path.abspath(__file__))
          session_dir = os.path.join(base_dir, "sessions")
    
          # 如果 sessions目录不存在,则创建 sessions
          if not os.path.exists(session_dir):
              os.makedirs(session_dir)
    
          #保存会话数据
          filename_safe = st.session_state.current_session
          filename = f"{filename_safe}.json"
          file_path = os.path.join(session_dir, filename)
          with open(file_path, "w", encoding="utf-8") as f:
              json.dump(session_data, f, ensure_ascii=False, indent=4)

    #--------------------保存当前会话信息函数-------------------------------

    #--------------------加载所有会话列表信息函数----------------------------
    def load_sessions():
    session_list = []
    #获取会话文件所在目录
    base_dir = get_base_dir()
    session_dir = os.path.join(base_dir, "sessions")
    #加载session目录下的文件
    if os.path.exists(session_dir):
    file_list = os.listdir(session_dir)
    for file_name in file_list:
    if file_name.endswith(".json"):
    session_list.append(file_name[:-5])
    session_list.sort(reverse=True) #排序,降序排序
    return session_list
    #--------------------加载所有会话列表信息函数----------------------------

    #--------------------加载指定会话信息函数----------------------------
    def load_session(session_name):
    try:
    # 以当前py脚本所在【第三章】文件夹为基准
    base_dir = get_base_dir()
    session_name = os.path.join(base_dir, f"sessions/{session_name}.json")
    #加载指定会话信息
    if os.path.exists(session_name):
    with open(session_name, "r", encoding="utf-8") as f:
    session_data = json.load(f)
    st.session_state.input = session_data["input"]
    st.session_state.current_session = session_data["current_session"]
    st.session_state.nick_name = session_data["nick_name"]
    st.session_state.character = session_data["character"]
    except Exception:
    st.error("加载会话失败!")
    #--------------------加载指定会话信息函数----------------------------

    #-------------------------网页聊天信息的记忆存储---------------------
    #初始化聊天信息
    if 'input' not in st.session_state:
    st.session_state['input'] = []
    #名字记忆单元,初始化为"小甜甜"
    if 'nick_name' not in st.session_state:
    st.session_state['nick_name'] = "小甜甜"
    #性格记忆单元,初始化为"活泼开朗的东北姑娘"
    if 'character' not in st.session_state:
    st.session_state['character'] = "活泼开朗的东北姑娘"
    #会话标识记忆单元
    if "current_session" not in st.session_state:
    st.session_state.current_session = generate_session_id()

    -------------------------网页聊天信息的记忆存储---------------------

    #设置页面的配置项
    st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
    )

    #大标题
    st.title("AI智能伴侣")

    #Logo
    st.logo("第三章/resouces/logo.jpg")

    #----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------
    with st.sidebar:
    #------会话信息--------
    st.subheader("AI控制面板")
    #新建会话按钮
    if st.button("新建会话",icon="🚀",width="stretch"):
    #保存当前会话信息
    session_save()
    #创建新的会话
    if st.session_state.input : #如果聊天消息非空,True;否则,False
    st.session_state.input = []
    st.session_state.current_session = generate_session_id()
    st.session_state.nick_name = "小甜甜"
    st.session_state.character = "活泼开朗的东北姑娘"
    #保存新建会话信息
    session_save()
    #会话历史
    st.text("会话历史")
    session_list = load_sessions()
    for session in session_list:
    col1, col2 = st.columns([4,1])
    with col1:
    if st.button(session, width="stretch", icon="📘",key=f"load_{session}",type= "primary" if session==current_session_safe else "secondary"):
    load_session(session)
    st.rerun()

    复制代码
              with col2:
                  if st.button("", width="stretch", icon="❌",key=f"delete_{session}"):
                      pass
          #------会话信息--------
    
          #------伴侣信息--------
          st.subheader("伴侣信息")
          #昵称输入框
          nick_name = st.text_input("昵称",placeholder="请输入伴侣昵称",value= st.session_state.nick_name)
          if nick_name:
              st.session_state['nick_name'] = nick_name  #名字记忆存储
          #性格输入框
          character = st.text_area("性格",placeholder="请输入伴侣性格",value= st.session_state.character)
          if character:
              st.session_state['character'] = character  #性格记忆存储
          # ------伴侣信息--------

    #----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------

    #-------------------------API调用前期准备--------------------------
    #设置系统提示词
    system_prompt = """
    你叫 %s,现在是用户的真实伴侣,请完全代入伴侣角色。
    规则:
    1.每次只回 1 条消息
    2.禁止任何场景或状态描述性文字
    3.匹配用户的语言
    4.回复简短,像微信聊天一样
    5.有需要的话可以用❤🌸等 emoji 表情
    6.用符合伴侣性格的方式对话
    7.回复的内容,要充分体现伴侣的性格特征
    伴侣性格:
    ‑ %s
    你必须严格遵守上述规则来回复用户。
    """

    创建与 AI 大模型交互的客户端对象(

    api_key = "***********************************************"
    client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key,
    )
    #-------------------------API调用前期准备--------------------------

    #展示聊天信息
    st.text(f"会话名称: {st.session_state.current_session}")
    for input in st.session_state['input']:
    st.chat_message(input["role"]).write(input["content"])
    #消息输入框
    prompt = st.chat_input("请输入您要问的问题")
    if prompt:
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    #调用 AI 大模型
    response = client.responses.create(
    model="doubao-seed-evolving",
    input= [
    {"role": "system", "content": system_prompt %(st.session_state.nick_name, st.session_state.character)},
    #解决大模型会话记忆问题
    *st.session_state['input'] #列表解包
    ],
    #要求流式输出
    stream= True
    )
    #-------------------------处理AI大模型的返回结果-----------------(流式输出解析方式)
    response_message = st.empty() #创建空容器,用于展示大模型的返回结果
    full_response = "" #用于存储大模型的返回结果
    for chunk in response:
    # 判断事件类型,取delta文本
    if chunk.type == "response.output_text.delta":
    content = chunk.delta
    full_response += content
    print(content, end="", flush=True)
    response_message.chat_message("assistant").write(full_response)
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": full_response})
    #保存会话信息
    session_save()
    st.rerun()

3.2.4 删除指定历史会话

本模块完成需要完成功能:当点击指定历史会话的删除按钮时,删除该历史会话信息

执行的操作有:

  • 删除指定历史会话功能(删除指定历史会话信息函数)

代码如下:

复制代码
import streamlit as st
import os
from openai import OpenAI
import json
from datetime import datetime

#--------------------生成会话标识函数----------------------------------
def generate_session_id():
    return datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
#--------------------生成会话标识函数----------------------------------

#--------------------保存当前会话信息函数-------------------------------
def session_save():
    if st.session_state.current_session:
        # 构建新的会话对象
        session_data = {
            "nick_name": st.session_state.nick_name,
            "character": st.session_state.character,
            "current_session": st.session_state.current_session,
            "input": st.session_state.input
        }

        # 以当前py脚本所在【第三章】文件夹为基准
        base_dir = os.path.dirname(os.path.abspath(__file__))
        session_dir = os.path.join(base_dir, "sessions")

        # 如果 sessions目录不存在,则创建 sessions
        if not os.path.exists(session_dir):
            os.makedirs(session_dir)

        #保存会话数据
        filename_safe = st.session_state.current_session
        filename = f"{filename_safe}.json"
        file_path = os.path.join(session_dir, filename)
        with open(file_path, "w", encoding="utf-8") as f:
            json.dump(session_data, f, ensure_ascii=False, indent=4)
#--------------------保存当前会话信息函数-------------------------------

#--------------------加载所有会话列表信息函数----------------------------
def load_sessions():
    session_list = []
    #获取会话文件所在目录
    base_dir = os.path.dirname(os.path.abspath(__file__))
    session_dir = os.path.join(base_dir, "sessions")
    #加载session目录下的文件
    if os.path.exists(session_dir):
        file_list = os.listdir(session_dir)
        for file_name in file_list:
            if file_name.endswith(".json"):
                session_list.append(file_name[:-5])
    session_list.sort(reverse=True)  #排序,降序排序
    return session_list
#--------------------加载所有会话列表信息函数----------------------------

#--------------------加载指定会话信息函数----------------------------
def load_session(session_name):
    try:
        # 以当前py脚本所在【第三章】文件夹为基准
        base_dir = os.path.dirname(os.path.abspath(__file__))
        session_name = os.path.join(base_dir, f"sessions/{session_name}.json")
        #加载指定会话信息
        if os.path.exists(session_name):
            with open(session_name, "r", encoding="utf-8") as f:
                session_data = json.load(f)
                st.session_state.input = session_data["input"]
                st.session_state.current_session = session_data["current_session"]
                st.session_state.nick_name = session_data["nick_name"]
                st.session_state.character = session_data["character"]
    except Exception:
        st.error("加载会话失败!")
#--------------------加载指定会话信息函数----------------------------

#--------------------删除指定会话信息函数----------------------------
def delete_session(session_name):
    try:
        base_dir = os.path.dirname(os.path.abspath(__file__))
        #用单独的变量存文件路径,不要覆盖传入的会话名
        file_path = os.path.join(base_dir, f"sessions/{session_name}.json")
        if os.path.exists(file_path):
            os.remove(file_path)    #删除文件
            #只有删除的是当前正在展示的会话,才清空聊天信息并开启新会话
            if session_name == st.session_state.current_session:
                st.session_state.input = []
                st.session_state.current_session = generate_session_id()
                st.session_state.nick_name = "小甜甜"
                st.session_state.character = "活泼开朗的东北姑娘"
    except Exception:
        st.error("删除会话失败!")
#--------------------删除指定会话信息函数----------------------------

#-------------------------网页聊天信息的记忆存储---------------------
#初始化聊天信息
if 'input' not in st.session_state:
    st.session_state['input'] = []
#名字记忆单元,初始化为"小甜甜"
if 'nick_name' not in st.session_state:
    st.session_state['nick_name'] = "小甜甜"
#性格记忆单元,初始化为"活泼开朗的东北姑娘"
if 'character' not in st.session_state:
    st.session_state['character'] = "活泼开朗的东北姑娘"
#会话标识记忆单元
if "current_session" not in st.session_state:
    st.session_state.current_session = generate_session_id()
# -------------------------网页聊天信息的记忆存储---------------------

#设置页面的配置项
st.set_page_config(
    page_title="AI智能伴侣",
    page_icon="🤖",
    #布局
    layout="wide",
    #侧边栏状态
    initial_sidebar_state="expanded",
    menu_items={}
)

#大标题
st.title("AI智能伴侣")

#Logo
st.logo("第三章/resouces/logo.jpg")

#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------
with st.sidebar:
    # ------会话信息--------
    st.subheader("AI控制面板")
    # 新建会话按钮
    if st.button("新建会话", icon="🚀", width="stretch"):
        # 保存当前会话信息
        session_save()
        # 创建新的会话
        if st.session_state.input:  # 如果聊天消息非空,True;否则,False
            st.session_state.input = []
            st.session_state.current_session = generate_session_id()
            st.session_state.nick_name = "小甜甜"
            st.session_state.character = "活泼开朗的东北姑娘"
            # 保存新建会话信息
            session_save()
    #会话历史
    st.text("会话历史")
    session_list = load_sessions()
    for session in session_list:
        col1, col2 = st.columns([4, 1])
        with col1:
            if st.button(session, width="stretch", icon="📘", key=f"load_{session}", type="primary" if session == st.session_state.current_session else "secondary"):
                load_session(session)
                st.rerun()

        with col2:
            if st.button("", width="stretch", icon="❌", key=f"delete_{session}"):
                delete_session(session)
                st.rerun()
    # ------会话信息--------

    #------伴侣信息--------
    st.subheader("伴侣信息")
    #昵称输入框
    nick_name = st.text_input("昵称",placeholder="请输入伴侣昵称",value= st.session_state.nick_name)
    if nick_name:
        st.session_state['nick_name'] = nick_name  #名字记忆存储
    #性格输入框
    character = st.text_area("性格",placeholder="请输入伴侣性格",value= st.session_state.character)
    if character:
        st.session_state['character'] = character  #性格记忆存储
    # ------伴侣信息--------
#----------------------左侧侧边栏. with: streamlit中上下文管理器---------------------------


#-------------------------API调用前期准备--------------------------
#设置系统提示词
system_prompt = """
            你叫 %s,现在是用户的真实伴侣,请完全代入伴侣角色。
            规则:
                1.每次只回 1 条消息
                2.禁止任何场景或状态描述性文字
                3.匹配用户的语言
                4.回复简短,像微信聊天一样
                5.有需要的话可以用❤🌸等 emoji 表情
                6.用符合伴侣性格的方式对话
                7.回复的内容,要充分体现伴侣的性格特征
                伴侣性格:
                    ‑ %s
                你必须严格遵守上述规则来回复用户。
    """

# 创建与 AI 大模型交互的客户端对象(
api_key = "***************************"
client = OpenAI(
    base_url="https://ark.cn-beijing.volces.com/api/v3",
    api_key=api_key
)
#-------------------------API调用前期准备--------------------------



#展示聊天信息
st.text(f"会话名称: {st.session_state.current_session}")
for input in st.session_state['input']:
        st.chat_message(input["role"]).write(input["content"])

#消息输入框
prompt = st.chat_input("请输入您要问的问题")
if prompt: #字符串会自动转换为布尔值,如果字符串非空,为True;否则为False
    st.chat_message("user").write(prompt)
    print("--------------------->调用AI大模型,提示词:",prompt)
    #保存用户输入的提示词
    st.session_state['input'].append({"role": "user","content": prompt})
    #调用 AI 大模型
    response = client.responses.create(
        model="doubao-seed-evolving",
        input= [
            {"role": "system", "content": system_prompt %(st.session_state['nick_name'], st.session_state['character'])},
            #解决大模型会话记忆问题
            *st.session_state['input']  #列表解包
        ],
        #要求流式输出
        stream= True
    )
    #-------------------------处理AI大模型的返回结果-----------------(流式输出解析方式)
    response_message = st.empty() #创建空容器,用于展示大模型的返回结果
    full_response = ""   #用于存储大模型的返回结果
    for chunk in response:
            # 判断事件类型,取delta文本
            if chunk.type == "response.output_text.delta":
                content = chunk.delta
                full_response += content
                print(content, end="", flush=True)
                response_message.chat_message("assistant").write(full_response)
    #保存大模型返回的结果
    st.session_state['input'].append({"role": "assistant","content": full_response})
    #保存会话信息
    session_save()
    st.rerun()
相关推荐
jonyleek2 小时前
JVS-Logic 实践指南:基于私有化与柔性配置的企业级逻辑引擎落地方法
人工智能·低代码·私有化部署·企业集成·逻辑引擎·流程编排·jvs
诗句藏于尽头2 小时前
deepseek harness对接商汤科技免费大模型使用教程
人工智能·科技·学习
兰亭妙微UI设计公司2 小时前
兰亭妙微用户体验公司分享:《AI 体验设计》第 3 部分:指导原则
人工智能
阿萨德528号2 小时前
DeepSeek Harness 开源了,但先别叫“正式版”:从封闭内测到 Developer Preview,只隔了两周
人工智能·deepseek·harness
轻松,带微笑2 小时前
美拓GEO平台技术升级:六大AI平台监测+多模态视频能力,赋能品牌抢占AI营销新赛道
人工智能
MEIXIFU12 小时前
便利店实际经营面积怎么选最合适
大数据·人工智能·物联网·生活·迭代加深
就是一顿骚操作3 小时前
VGG:用小卷积块把 CNN 做深的经典解读
人工智能·深度学习·神经网络·cnn·论文解读
奈斯先生Vector3 小时前
AI 视频不是会动的图片:用 Shot Contract、时间码与音画质检构建可交付流水线
人工智能·重构·架构·prompt·aigc·音视频
男孩李3 小时前
浅谈JiuwenSwarm安装
人工智能·语言模型·自然语言处理