一、准备工作

1.1、魔搭社区下载大模型

通义千问2.5-7B-Instruct · 模型库

from modelscope.hub.snapshot_download import snapshot_download
llm_model_dir = snapshot_download('Qwen/Qwen2.5-7B-Instruct',cache_dir='models')

1.2、启动vllm大模型 

python -m vllm.entrypoints.openai.api_server --port 10222 --model /home/AI_big_model/models/Qwen/Qwen2.5-7B-Instruct --served-model-name Qwen2.5-7B-Instruct

二、Fastapi后端

        FastAPI 是一个用于构建API的现代化、快速(高性能)的Web框架,使用Python 3.7+的标准类型提示。它的性能媲美Node.js和Go,是基于Python的框架中最快的之 一。

主要特点:

        高性能:与Starlette、Pydantic等框架深度集成,性能优异。

        简洁明了:基于类型提示(Type Hints),使得代码更加简洁且具备良好的可读 性。

        自动生成文档:自动生成Swagger UI和ReDoc文档,方便开发者查看和测试 API。

        异步支持:原生支持Python的async和await,适合处理异步任务。

pip install fastapi

pip install uvicorn 

# 导入必要的库
from fastapi import FastAPI, Body  # FastAPI框架和Body请求体
from openai import AsyncOpenAI  # OpenAI异步客户端
from typing import List  # 类型提示
from fastapi.responses import StreamingResponse  # 流式响应

# 初始化FastAPI应用
app = FastAPI()

# 初始化openai的客户端
api_key = "EMPTY"  # 空API密钥(因为使用本地部署的模型)
base_url = "http://127.0.0.1:10222/v1"  # 本地部署的模型API地址
aclient = AsyncOpenAI(api_key=api_key, base_url=base_url)  # 创建异步客户端实例

# 初始化对话列表(全局变量)
messages = []

# 定义路由,实现接口对接
@app.post("/chat")
async def chat(
    query: str = Body(default='你是谁?', description="用户输入"),  # 用户输入的查询文本
    sys_prompt: str = Body("你是一个有用的助手。", description="系统提示词"),  # 系统角色设定
    history: List = Body([], description="历史对话"),  # 历史对话记录
    history_len: int = Body(1, description="保留历史对话的轮数"),  # 保留的历史对话轮数
    temperature: float = Body(0.5, description="LLM采样温度"),  # 生成文本的随机性控制
    top_p: float = Body(0.5, description="LLM采样概率"),  # 核采样概率阈值
    max_tokens: int = Body(default=1024, description="LLM最大token数量")  # 生成的最大token数
):  
    global messages  # 使用全局的messages列表
    
    # 控制历史记录长度(只保留指定轮数的对话)
    if history_len > 0:
        history = history[-2 * history_len:]  # 每轮对话包含用户和AI两条记录,所以乘以2

    # 清空消息列表(每次请求都重新构建)
    messages.clear()
    # 添加系统提示词
    messages.append({"role": "system", "content": sys_prompt})

    # 在message中添加历史记录
    messages.extend(history)

    # 在message中添加用户当前的查询
    messages.append({"role": "user", "content": query})

    # 发送请求到本地部署的模型
    response = await aclient.chat.completions.create(
        model="Qwen2.5-7B-Instruct",  # 使用的模型名称
        messages=messages,  # 完整的对话上下文
        max_tokens=max_tokens,  # 最大token数
        temperature=temperature,  # 温度参数
        top_p=top_p,  # 核采样参数
        stream=True  # 启用流式输出
    )

    # 定义生成响应的异步生成器函数
    async def generate_response():
        # 遍历流式响应的每个chunk
        async for chunk in response:
            chunk_msg = chunk.choices[0].delta.content  # 获取当前chunk的文本内容
            if chunk_msg:  # 如果有内容则yield
                yield chunk_msg
    
    # 返回流式响应,媒体类型为纯文本
    return StreamingResponse(generate_response(), media_type="text/plain")

# 主程序入口
if __name__ == "__main__":
    import uvicorn
    # 启动FastAPI应用
    # 参数说明:
    # "fastapi_bot:app" - 要运行的模块和应用实例
    # host="0.0.0.0" - 监听所有网络接口
    # port=6066 - 服务端口
    # log_level="info" - 日志级别
    # reload=True - 开发模式下自动重载
    uvicorn.run("fastapi_bot:app", host="0.0.0.0", port=6066, log_level="info", reload=True)

三、streamlit界面设计

        Streamlit 是一个非常方便的 Python 库,用来快速构建数据驱动的 Web 应用。在这 个项目中,Streamlit 将用于展示聊天界面并与后端进行交互。

API链接:API Reference - Streamlit Docs

pip install streamlit==1.39.0 

导入依赖

import streamlit as st
import requests

 页面设置

st.set_page_config(page_title="ChatBot", page_icon="🤖", layout="centered")
st.title("🤖 聊天机器人")

 侧边栏配置

with st.sidebar:
    st.title("ChatBot")
    sys_prompt = st.text_input("系统提示词:", value="你是一个有用的助手")
    history_len=st.slider("保留历史对话的数量",min_value=-1,max_value=10,value=1,step=1)
    temperature=st.slider("temperature",min_value=0.01,max_value=2.0,value=0.5,step=0.01)
    top_p=st.slider("top_p",min_value=0.01,max_value=2.0,value=0.5,step=0.01)
    max_tokens=st.slider("max_tokens",min_value=256,max_value=4096,value=1024,step=8)
    stream=st.checkbox("stream",value=True)

 聊天历史记录管理

if "history" not in st.session_state:
    st.session_state.history = []
for messgae in st.session_state.history:
    with st.chat_message(messgae["role"]):
        st.markdown(messgae["content"])

 清空聊天记录

def clear_chat_history():
    st.session_state.history = []
st.button("清空聊天历史", on_click=clear_chat_history)

接受用户输入并显示消息 

if prompt := st.chat_input("请输入你的内容"):
    with st.chat_message('user'):
        st.markdown(prompt)

与后端 Fastapi通信

    response = requests.post('http://127.0.0.1:6066/chat', json=data, stream=True)
    if response.status_code==200:
        chunks = ""
        assistant_placeholder=st.chat_message("assistant")
        assistant_text=assistant_placeholder.markdown("")
        if stream:  # 流式输出
            for chunk in response.iter_content(chunk_size=None, decode_unicode=True):
                # 处理响应的内容,并累加起来
                chunks += chunk
                # 实时显示和更新助手的消息
                assistant_text.markdown(chunks)
        else:
            for chunk in response.iter_content(chunk_size=None, decode_unicode=True):
                chunks += chunk
            assistant_text.markdown(chunks)

四、Fastapi+streamlit

# 导入必要的库
import streamlit as st  # 用于构建Web应用的库
import requests  # 用于发送HTTP请求

# 设置页面配置
st.set_page_config(
    page_title="ChatBot",  # 页面标题
    page_icon="🤖",  # 页面图标
    layout="centered"  # 布局方式
)
st.title("🤖 聊天机器人")  # 主标题

# 定义清空聊天历史的函数
def clear_chat_history():
    st.session_state.history = []  # 重置聊天历史为空列表

# 侧边栏设置
with st.sidebar:
    st.title("ChatBot")  # 侧边栏标题
    # 系统提示词输入框
    sys_prompt = st.text_input("系统提示词:", value="你是一个有用的助手")
    # 历史对话轮数滑块
    history_len = st.slider(
        "保留历史对话的数量",
        min_value=-1,  # -1表示保留全部历史
        max_value=10,
        value=1,
        step=1
    )
    # 温度参数滑块
    temperature = st.slider(
        "temperature",
        min_value=0.01,
        max_value=2.0,
        value=0.5,
        step=0.01
    )
    # top_p参数滑块
    top_p = st.slider(
        "top_p",
        min_value=0.01,
        max_value=2.0,
        value=0.5,
        step=0.01
    )
    # 最大token数滑块
    max_tokens = st.slider(
        "max_tokens",
        min_value=256,
        max_value=4096,
        value=1024,
        step=8
    )
    # 是否流式输出的复选框
    stream = st.checkbox("stream", value=True)
    # 清空聊天历史按钮
    st.button("清空聊天历史", on_click=clear_chat_history)

# 初始化聊天历史
if "history" not in st.session_state:
    st.session_state.history = []  # 如果不存在则创建空列表

# 显示历史消息
for messgae in st.session_state.history:
    with st.chat_message(messgae["role"]):  # 根据角色创建消息气泡
        st.markdown(messgae["content"])  # 显示消息内容

# 获取用户输入
if prompt := st.chat_input("请输入你的内容"):
    # 显示用户消息
    with st.chat_message('user'):
        st.markdown(prompt)
        # 准备请求数据
        data = {
            "query": prompt,  # 用户输入
            "sys_prompt": sys_prompt,  # 系统提示词
            "history_len": history_len,  # 历史对话轮数
            "history": st.session_state.history,  # 历史对话
            "temperature": temperature,  # 温度参数
            "top_p": top_p,  # top_p参数
            "max_tokens": max_tokens  # 最大token数
        }
    # 发送POST请求到FastAPI服务
    response = requests.post(
        'http://127.0.0.1:6066/chat',  # FastAPI服务地址
        json=data,  # 请求体数据
        stream=True  # 启用流式接收
    )
    
    # 处理成功响应
    if response.status_code == 200:
        chunks = ""  # 初始化内容容器
        # 创建助手消息占位符
        assistant_placeholder = st.chat_message("assistant")
        assistant_text = assistant_placeholder.markdown("")  # 初始空内容
        
        if stream:  # 流式输出模式
            for chunk in response.iter_content(chunk_size=None, decode_unicode=True):
                # 处理响应的内容,并累加起来
                chunks += chunk
                # 实时显示和更新助手的消息
                assistant_text.markdown(chunks)
        else:  # 非流式模式
            for chunk in response.iter_content(chunk_size=None, decode_unicode=True):
                chunks += chunk
            assistant_text.markdown(chunks)
        
        # 将对话添加到历史记录
        st.session_state.history.append({"role": "user", "content": prompt})
        st.session_state.history.append({"role": "assistant", "content": chunks})

Logo

更多推荐