吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 447|回复: 8
收起左侧

[经验求助] 求助大佬,flask流式输出怎么弄

[复制链接]
HerbertQ 发表于 2024-6-26 15:07
100吾爱币
我用flask搭建了一个智谱清言api的调用小demo,学习练手的。运行app.py后,返回的信息要等全部信息结束后才显示。我希望返回多少显示多少,体验好些,我发现这种ai页面都是一个字一个字显示的,叫流式输出吧。我折腾了很久都实现不了,不是这里有错就是那里有错。请大佬不吝赐教,帮忙修改下代码,看看怎么实现的。

这是app.py的代码
[Python] 纯文本查看 复制代码
from flask import Flask, render_template, request, jsonify
from zhipuai import ZhipuAI

app = Flask(__name__)
api_key = ""  # 替换为你的API密钥
model_name = "glm-4-0520"

# 初始化ZhipuAI客户端
client = ZhipuAI(api_key=api_key)

# 初始化对话上下文
context = [
    {
        "role": "system",
        "content": "你是一个乐于解答各种问题的助手,你的任务是为用户提供专业、准确、有见地的建议。"
    }
]

@app.route('/')
def index():
    return render_template('index.html')  # 渲染前端模板

@app.route('/chat', methods=['POST'])
def chat():
    global context 
    
    # 获取前端发送的用户输入
    user_input = request.json.get('input', '')
    
    # 如果用户输入是'exit',则结束对话
    if user_input.lower() == 'exit':
        return jsonify({'response': '对话已结束。'})

    # 将用户输入添加到上下文中
    context.append({
        "role": "user",
        "content": user_input
    })

    # 发送请求到模型
    response = client.chat.completions.create(
        model="glm-4-0520",
        messages=context,
        top_p=0.7,
        temperature=0.95,
        max_tokens=4095,
        tools=[{"type":"web_search","web_search":{"search_result":True}}],
        stream=True,
    )

    # 处理响应并打印结果
    full_response = ""
    for chunk in response:
        for choice in chunk.choices:
            delta = choice.delta
            full_response += delta.content

            # 如果finish_reason是'stop',说明这是最后一个Chunk或者句子已经完成
            if choice.finish_reason == 'stop':
                break
        else:
            # 如果这个Chunk中没有finish_reason为'stop'的Choice,则继续下一个Chunk
            continue

        # 当找到一个finish_reason为'stop'的Choice时,打印完整的句子
        return jsonify({'response': full_response})

    # 清空full_response,准备下一次循环
    full_response = ""

    # 可以选择性地清理或保留部分上下文,这里简单地将“user”消息移除,保留系统消息和其他上下文
    context = [message for message in context if message["role"] != "user"]

if __name__ == '__main__':
    app.run(debug=True)


这是前端页面的代码:
[HTML] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Flask Chat App</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>

<h1>简易ai聊天</h1>
<textarea id="chat-input" placeholder="请输入你的问题或对话内容(输入'exit'结束对话)"></textarea>
<button>发送</button>
<div id="chat-output"></div>

<script>
function sendMessage() {
    var input = $('#chat-input').val();
    $.ajax({
        url: '/chat',
        type: 'POST',
        contentType: 'application/json',
        data: JSON.stringify({input: input}),
        success: function(response) {
            $('#chat-output').append('<p>' + response.response + '</p>');
            $('#chat-input').val(''); // 清空输入框
        },
        error: function(error) {
            console.error(error);
            alert('发送失败,请稍后再试。');
        }
    });
}
</script>

</body>
</html>

最佳答案

查看完整内容

后端代码 [mw_shl_code=python,true] import json from flask import Flask, Response, render_template, request from zhipuai import ZhipuAI app = Flask(__name__) api_key = "" # 替换为你的API密钥 model_name = "glm-4-0520" # 初始化ZhipuAI客户端 client = ZhipuAI(api_key=api_key) # 初始化对话上下文 context = [ { "role": "system", "content": "你是一个乐于解答各种问 ...

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

寒江雪2018 发表于 2024-6-26 15:07
后端代码
[Python] 纯文本查看 复制代码
import json

from flask import Flask, Response, render_template, request
from zhipuai import ZhipuAI

app = Flask(__name__)
api_key = ""  # 替换为你的API密钥
model_name = "glm-4-0520"

# 初始化ZhipuAI客户端
client = ZhipuAI(api_key=api_key)

# 初始化对话上下文
context = [
    {
        "role": "system",
        "content": "你是一个乐于解答各种问题的助手,你的任务是为用户提供专业、准确、有见地的建议。",
    }
]


@app.route("/")
def index():
    return render_template("index.html")  # 渲染前端模板


def generate_chat(content):
    global context

    # 将用户输入添加到上下文中
    context.append({"role": "user", "content": content})

    # 发送请求到模型
    response = client.chat.completions.create(
        model="glm-4-0520",
        messages=context,
        top_p=0.7,
        temperature=0.95,
        max_tokens=4095,
        tools=[{"type": "web_search", "web_search": {"search_result": True}}],
        stream=True,
    )

    for chunk in response:
        for choice in chunk.choices:
            yield json.dumps({"message": choice.delta.content})

            # 如果finish_reason是'stop',说明这是最后一个Chunk或者句子已经完成
            if choice.finish_reason == "stop":
                return
        else:
            # 如果这个Chunk中没有finish_reason为'stop'的Choice,则继续下一个Chunk
            continue
    return


@app.route("/chat", methods=["POST"])
def chat():
    global context

    # 获取前端发送的用户输入
    user_input = request.json.get("input", "")

    # 如果用户输入是'exit',则结束对话
    if user_input.lower() == "exit":
        context = []
        return Response(
            json.dumps({"message": "对话已结束"}), content_type="application/json"
        )

    return Response(generate_chat(user_input), content_type="application/json")


if __name__ == "__main__":
    app.run(debug=True)


前端代码
[JavaScript] 纯文本查看 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Flask Chat App</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>

<body>

    <h1>简易ai聊天</h1>
    <textarea id="chat-input" placeholder="请输入你的问题或对话内容(输入'exit'结束对话)"></textarea>
    <button onClick="sendMessage()">发送</button>
    <div id="chat-output"></div>

    <script>
        function sendMessage() {
            var input = $('#chat-input').val();
            fetch('/chat', {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify({ input: input }),      
            })
                .then(response => {
                    // 检查响应是否成功
                    if (!response.ok) {
                        throw new Error(`HTTP error! Status: ${response.status}`);
                    }

                    // 处理数据流
                    return handleStreamResponse(response);
                })
                .catch(error => {
                    console.error('Error fetching data:', error);
                });
        }

        const chatOut = document.getElementById('chat-output');

        // 定义一个函数来处理每次接收到的数据
        function handleStreamResponse(response) {
            const outPut = document.createElement('p');
            chatOut.appendChild(outPut);
            const reader = response.body.getReader();

            function read() {
                return reader.read().then(({ done, value }) => {
                    if (done) {
                        console.log('Stream complete');
                        return;
                    }

                    // 处理接收到的数据,这里假设数据是 JSON 格式
                    const text = new TextDecoder().decode(value);
                    const data = JSON.parse(text);

                    // 将数据展示在页面上
                    const span = document.createElement('span');
                    span.textContent = data.message;
                    outPut.appendChild(span);

                    // 继续读取下一部分数据
                    return read();
                });
            }

            return read();
        }


    </script>

</body>

</html>

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
HerbertQ + 1 + 1 这是真大佬

查看全部评分

 楼主| HerbertQ 发表于 2024-6-26 15:59
 楼主| HerbertQ 发表于 2024-6-26 16:57
 楼主| HerbertQ 发表于 2024-6-26 18:42
在线坐等大佬解答
 楼主| HerbertQ 发表于 2024-6-26 20:26
没有大佬帮助解答吗
 楼主| HerbertQ 发表于 2024-6-27 08:59
没有大佬解答吗?
 楼主| HerbertQ 发表于 2024-6-27 10:35
完全没有人关注。。。
 楼主| HerbertQ 发表于 2024-6-28 16:20
寒江雪2018 发表于 2024-6-26 15:07
后端代码
[mw_shl_code=python,true]
import json

感谢大佬指点
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-12 17:28

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表