克隆OpenAI(基于openai API和streamlit)
utils.py:
from langchain_openai import ChatOpenAI
from langchain.memory import ConversationBufferMemory
from langchain.chains import ConversationChain
import os
def get_chat_response(api_key,prompt,memory): # memory不能是函数的内部局部变量,否则会被清空;而且它是引用传递
model = ChatOpenAI(model="gpt-3.5-turbo",api_key=api_key,base_url="https://api.gptsapi.net/v1")
# 利用带记忆的对话链
chain = ConversationChain(llm=model,memory=memory)
result = chain.invoke(
{
"input":prompt # 默认提示模板里需要填充input变量
}
) #返回值是一个字典,包含了input、history、response
return result["response"]
# memory = ConversationBufferMemory(return_messages=True) 记得创建记忆的实例
# print(get_chat_response(os.getenv("OPENAI_API_KEY"),"牛顿提出过那些知名的定律?",memory))
# print(get_chat_response(os.getenv("OPENAI_API_KEY"),"我上一个问题是什么?",memory))
main.py:
import streamlit as st
from utils import get_chat_response
from langchain.memory import ConversationBufferMemory
st.title("克隆ChatCPT")
with st.sidebar:
api_key = st.text_input("请输入OpenAI API 密钥:",type="password")
st.markdown("[获取OpenAI API 密钥]()")
# 初始化会话状态(记忆和消息列表)
if "memory" not in st.session_state:
st.session_state.memory = ConversationBufferMemory(return_messages=True)
st.session_state.messages = [
{
"role":"ai", "content":"你好,我是你的AI助手,有什么可以帮你的吗?"
}
] #messages为了便于在前端页面上展示对话
# 显示历史对话消息(初始显示)
for message in st.session_state.messages:
st.chat_message(message["role"]).write(message["content"])
# 获取用户输入
prompt = st.chat_input()
if prompt:
if not api_key:
st.info("请输入你的OpenAI API密钥")
st.stop()
st.session_state.messages.append({"role":"human","content":prompt}) #将用户提问封装成消息对象,并添加进messages列表
st.chat_message("human").write(prompt) # 在页面显示该消息内容
# 获取AI回复
with st.spinner("AI正在思考中,请稍等···"):
response = get_chat_response(api_key=api_key,prompt=prompt,memory=st.session_state.memory)
st.session_state.messages.append({"role":"ai","content":response}) #将AI的回复封装成消息对象,并添加进messages列表
st.chat_message("ai").write(response) #在页面上显示该消息内容
补充:
1、初始化会话状态
- 如果会话状态中没有
memory
变量,则创建一个ConversationBufferMemory
实例,并将return_messages
参数设置为True
,表示返回消息列表。(记忆)- 同时,初始化会话状态中的
messages
列表,包含一条初始的 AI 回复消息。(显示在页面上的消息列表)2、显示历史对话信息
遍历会话状态中的
messages
列表,使用st.chat_message
函数根据消息的角色(human
或ai
)创建聊天消息框,并自动选择图标和样式来显示消息内容。3、获取用户输入
st.chat_input
:创建一个聊天输入框,获取用户输入的消息。- 如果用户输入了消息,首先检查是否输入了 API 密钥,如果没有输入,则显示提示信息并停止程序执行。
- 将用户输入的消息添加到会话状态的
messages
列表中,并在界面上显示该消息。4、获得AI的回复并显示
- 调用
get_chat_response
函数,传入 API 密钥、用户输入和对话记忆,获取 AI 的回复。- 将 AI 的回复封装成消息对象,添加到会话状态的
messages
列表中,并在界面上显示该消息。5、关于messages和memory
基于数据结构的灵活性不同、功能侧重点不同以及代码的可读性和维护性,建议将memory和messages分开使用,各自发挥其优势。
6、
st.session_state.memory = ConversationBufferMemory(return_messages=True)
# 等价于st.session_state["memory"]=ConversationBufferMemory(return_messages=True)
st.session_state
是 Streamlit 提供的一个用于在应用会话期间存储和共享数据的对象,从底层实现来讲,它的行为类似于 Python 的字典(dict
)。所以可以有两种访问方式:
对象的属性访问—— .
obj = MyClass() obj.name = "John" # 设置属性 print(obj.name) # 访问属性
字典的键值对访问—— [ ]
my_dict = {} my_dict["name"] = "John" # 设置键值对 print(my_dict["name"]) # 获取键对应的值