项目完整代码
# 导入streamlit库
import streamlit as st
import os
from openai import OpenAI
from datetime import datetime
import json
#保存会话信息的函数
def save_session():
# 格式化
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,
"messages": st.session_state.messages
}
# 如果session文件不存在,则创建文件
if not os.path.exists("sessions"):
os.mkdir("sessions")
# 保存会话信息
with open(f"sessions/{st.session_state.current_session}.json", "w", encoding="utf-8") as f:
print("------->会话标识:",st.session_state.current_session)
json.dump(session_data, f, ensure_ascii=False, indent=4)
#加载所有的会话信息
def load_sessions():
#创建一个空列表
file_list = []
if os.path.exists("sessions"):
all_file = os.listdir("sessions")
for filename in all_file:
if filename.endswith(".json"):
file_list.append(filename[:-5])
file_list.sort(reverse=True)#倒序
return file_list
#加载会话信息
def load_session(session_name):
try:
with open(f"sessions/{session_name}.json", "r", encoding="utf-8") as f:
session_data = json.load(f)
st.session_state.nick_name = session_data["nick_name"]
st.session_state.character = session_data["character"]
st.session_state.current_session = session_name
st.session_state.messages = session_data["messages"]
except Exception:
st.error("会话加载失败")
# 删除会话信息
def delete_session(session_name):
try:
if os.path.exists(f"sessions/{session_name}.json"):
os.remove(f"sessions/{session_name}.json")
st.success("会话删除成功")
except Exception:
st.error("会话删除失败")
#保存当前时间的函数
def save_current_time():
return datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
# 初始化聊天信息
if "messages" not in st.session_state:
st.session_state.messages = [] #列表用来存放value:{"role": "user", "content": "你好"}
# 初始化昵称
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 = save_current_time()
# 页面布局
st.set_page_config(
page_title="Ai智能伴侣",
page_icon="😻",
layout="wide",
initial_sidebar_state="expanded",
menu_items={}
)
# 大标题
st.title("Ai智能伴侣")
st.text(f"当前会话名称:{st.session_state.current_session}")
#左侧的侧边栏
with st.sidebar:
#会话信息
st.subheader("Ai控制面板")
if st.button("新建会话",width="stretch",icon="✏️"):
#保存会话信息
save_session()
#新建会话信息
if st.session_state.messages:
st.session_state.messages = []
st.session_state.current_session = save_current_time()
save_session()
#会话历史
st.text("历史会话")
session_list = load_sessions()
for session in session_list:
print("------------>session目前的值为:",session)
coil1,coil2 = st.columns([4,1])
#加载会话信息
with coil1:
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 coil2:
if st.button("",width="stretch", icon="❌", key=f"delete_{session}"):
delete_session( session)
st.rerun()
# 分割线
st.divider()
#侧边栏标题
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
# 遍历聊天信息
for message in st.session_state.messages:
if message["role"] == "user":
st.chat_message("user").write(message["content"])
else:
st.chat_message("assistant").write(message["content"])
# 创建Openai的客户端client
client = OpenAI(api_key=os.environ.get('DEEPSEEK_API_KEY'),base_url="https://api.deepseek.com")
# 系统设定
System_prompt = """
你叫%s,现在是用户的真实伴侣,请完全代入伴侣角色。
规则:
1. 每次只回1条消息
2.禁止任何场景或状态描述性文字
3.匹配用户的语言
4.回复简短,像微信聊天一样
5.有需要的话可以用❤️🌸等emoji表情
6.用符合伴侣性格的方式对话
7.回复的内容,要充分体现伴侣的性格特征
伴侣性格:
%s
你必须严格遵守上述规则来回复用户。
"""
# 输入框
prompt = st.chat_input("快来和我一起聊天吧")
if prompt:# 判断输入框是否为空,如果不为空,则执行以下代码
st.chat_message("user").write(prompt)
#保存用户输入的提示词
st.session_state.messages.append({"role": "user", "content": prompt})
# 调用Ai大模型进行思考
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[
{"role": "system", "content": System_prompt%( st.session_state.nick_name,st.session_state.character)},
{"role": "user", "content": prompt},
#模型每次思考,都会保存在session_state.messages中,所以解包后的内容会作为模型输入
*st.session_state.messages
],
stream=True,
)
# #模型的回复(非流式输出)
# print("-------------->模型的回答:",response.choices[0].message.content)
# st.chat_message("assistant").write(response.choices[0].message.content)
# 创建一个空容器,用来保存模型回复
response_message = st.empty ()
# 流式输出
full_message = ""
for chunk in response:
if chunk.choices[0].delta.content is not None:
content = chunk.choices[0].delta.content
full_message += content
response_message.chat_message("assistant").write(full_message)
# 保存Ai的回复
st.session_state.messages.append({"role": "assistant", "content": full_message})
print("-------->",full_message)
save_session()
Ai应用开发核心技术模块
大模型部署方案
基于Ollama的本地部署方案
Ollama的概念:
Ollama 是一个开源的本地大语言模型运行框架,专为在本地机器上便捷部署和运行大型语言模型(LLM)而设计。
Ollama 支持多种操作系统,包括 macOS、Windows、Linux 以及通过 Docker 容器运行。
Ollama 提供对模型量化的支持,可以显著降低显存要求,使得在普通家用计算机上运行大型模型成为可能。
Ollama本地部署方法:
1. 在ollama中搜索要运行的模型,输入:
ollama run 模型名
如果模型未下载,输入命令可以自动下载,相反就是在终端运行模型并进行对话2. 设置ollama服务开机自动运行
3. ollama详细学习地址:https://www.runoob.com/ollama/ollama-tutorial.html
基于云端APi调用的方案
部署方案:
1. 通过国产或国外模型服务商调用API_key和模型进行交互
2. 参照官方文档格式进行调用
3. 例如deepseek官方文档:https://api-docs.deepseek.com/zh-cn/
HTTP协议
重要知识概念:
HTTP(超文本传输协议,Hypertext Transfer Protocol)是一种用于从网络传输超文本到本地浏览器的传输协议。它定义了客户端与服务器之间请求和响应的格式。HTTP 工作在 TCP/IP 模型之上,通常使用端口 80。
HTTPS(超文本传输安全协议,Hypertext Transfer Protocol Secure)是 HTTP 的安全版本,它在 HTTP 下增加了 SSL/TLS 协议,提供了数据加密、完整性校验和身份验证。HTTPS 通常使用端口 443。
HTTP/HTTPS都是基于C/S的架构(C/S:客户端/服务端)
HTTP请求数据格式:

HTTP响应数据格式:

状态码:
1. 200:客户端请求成功
3. 400:请求参数错误
4. 404:请求资源不存在,url输入有误或者网站资源已删除
5. 500:服务器端出现错误
参看方式:
1. 在浏览器查阅网页时按F12可以进入开发者工具

2. 点击数据后,可以看到HTTP的请求数据帧和响应数据帧


大模型交互方案
Ollama
# 导入requests 库
import requests
response = requests.post(
"http://localhost:11434/api/chat",
json={
"model": "deepseek-coder",
"messages": [
{
"role": "user",
"content": "你好,你能帮我写一段 Python 代码吗?"
}
],
"stream": False
}
)
print(response.json())
云端API调用模型(以deepseek为例)
# Please install OpenAI SDK first: pip3 install openai
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ.get('DEEPSEEK_API_KEY'),
base_url="https://api.deepseek.com")
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=False,
)
print(response.choices[0].message.content)api_key=os.environ.get('DEEPSEEK_API_KEY')指的是在环境变量中获取API_key(目的是为保护API_key)
具体步骤:
1. 在高级系统设置中添加用户的环境变量


2. 变量名:DEEPSEEK_API_KEY
3. 变量值为:获取的API_key
流式响应即( stream=true)
- 在选择流式响应后应更改输出的方式,因为流式输出时模型会一个一个token往外吐
- 在借助API访问模型实际上是通过HTTP协议来进行获取,所以我们需要查看模型响应时的响应数据格式
- 可以通过Apifox工具来进行获取,以下如图所示(仍需要查看官方文档,以下以deepseek为例):
/curl https://api.deepseek.com/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${DEEPSEEK_API_KEY}" \
-d '{
"model": "deepseek-v4-pro",
"messages": [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Hello!"}
],
"thinking": {"type": "enabled"},
"reasoning_effort": "high",
"stream": true # 开启流式响应
}'-H:表示请求头
Content-Type: application/json:表示为json格式的数据
Authorization: Bearer
-d:表示请求体
${DEEPSEEK_API_KEY}:表示要输入的Api_key
具体操作如下:


点击发送,查看响应的数据格式
可以看到数据是一条一条传输,如下所示:

每一条的响应数据格式如下:

具体代码如下:
#导入模块
import os
from openai import OpenAI
#创建OpenAI类的实例对象client,传入api_key,设置base_url
client = OpenAI(api_key=os.environ.get('DEEPSEEK_API_KEY'),base_url="https://api.deepseek.com")
#创建一个会话,用response接收模型回答
response = client.chat.completions.create(
model="deepseek-v4-pro",
messages=[
{"role": "system", "content": "You are a helpful assistant"},
{"role": "user", "content": "Hello"},
],
stream=True# 启用流式输出
)
# #输出模型回答(非流式)
# print(response.choices[0].message.content)
#输出模型回答(流式)
# 创建一个对象存储模型的回答
full_content = ""
for chunk in response:
current_answer = chunk.choices[0].delta.content
if current_answer: # 最后一个chunk可能为None,需要跳过
full_content += current_answer
print(current_answer, end="", flush=True) # 只打印新增内容,立即刷新缓冲区
print() # 最后换行具体修改:

大模型会话记忆方案(滚雪球式的)
思路:将自己与Ai的对话在喂给Ai,不断滚雪球
具体代码如下:

Streamlit构建页面
依据官方文档直接调用就行
官方地址:https://docs.streamlit.io/
文件基本操作
思路:就三步
打开文件
写入、读取文件
关闭文件
代码:
#读文件
# 打开文件
file = open("resource/新建 文本文档.txt", "r", encoding="utf-8")
#读取文件
print(file.read())
#关闭文件
file.close()
#创建一个文件
# 打开文件
file = open("resource/message.txt", "w", encoding="utf-8")
# 写入文件
file.write("静夜思\n\n")
file.write("床前明月光\n")
file.write("疑是地上霜\n")
file.write("举头望明月\n")
file.write("低头思故乡\n")进阶思路:如果操作文件过程中出现异常,应该怎么处理?
繁琐,不推荐:
# 写文件
# 打开文件
file = open("../第三章/resource/新建文本文档.txt", "w", encoding="utf-8")
try :
# 写入文件
file.write("静夜思\n\n")
file.write("床前明月光\n")
file.write("疑是地上霜\n")
file.write("举头望明月\n")
file.write("低头思故乡\n")
finally:
# 关闭文件
file.close()
# 关闭文件
file.close()推荐写法:
# 写文件
# 打开文件
with open("../第三章/resource/新建文本文档.txt", "w", encoding="utf-8") as file:
# 写入文件
file.write("静夜思\n\n")
file.write("床前明月光\n")
file.write("疑是地上霜\n")
file.write("举头望明月\n")
file.write("低头思故乡\n")
```
- with 是上下文管理器(Context Manager) 语句,用于自动管理资源的获取和释放,确保退出代码块时一定执行清理操作,即使发生异常。
## json操作
```
import json
user_info = {
"name": "王林",
"age": 18,
"sex": "男",
"habit":["看电影", "看小说", "看动画"],
}
# 写入json文件
with open("resource/user.json", "w", encoding="utf-8") as f:
json.dump(user_info, f, ensure_ascii=False, indent=4)
print("写入成功")
# 读取json文件
with open("resource/user.json", "r", encoding="utf-8") as f:
user_info = json.load(f)
print(user_info)在使用json存储数据时,需调用json库
json.dump(“要写入的数据”,''存储的文件名'')方法:
ensure_ascii=False: 关闭ascil,因为ascil只能存储数字与字母,无法存储中文字体,因为默认为true,所以在存储中文时要进行关闭
indent=:表示缩进,默认为None,建议进行缩进,数据格式清晰易查看
os/datetime模块
os:os 模块是 Python 与操作系统之间的桥梁,提供文件系统操作、进程管理、环境变量访问等跨平台能力。
以代码举例:

os.path.exists("sessions"):表示检验sessions路径是否存在,存在返回true; 不存在返回flase
os.listdir("sessions"):返回指定目录下的所有文件和子目录名称的列表(仅名字,不含路径前缀)。

os.mkdir(""): # 创建单层目录(父目录必须存在)

os.remove("") # 删除单层目录
Ai应用实战项目总结
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
评论交流
欢迎留下你的想法