首页 > 其他分享 >vllm+go||vllm+go-zero 流式输出

vllm+go||vllm+go-zero 流式输出

时间:2024-08-07 17:51:11浏览次数:11  
标签:Set http stream err Header zero go vllm

Golang 后端流式输出实现

以下是如何在 Golang 后端实现流式输出的步骤。

1. 后端 (Golang)

首先,你需要创建一个 HTTP 处理器来处理前端的请求,并设置响应头以支持 Server-Sent Events (SSE)。

import (
    "fmt"
    "net/http"
)

func streamHandler(w http.ResponseWriter, r *http.Request) {
    // 设置响应头
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    // 创建一个 flusher
    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
        return
    }

    // 模拟从模型获取数据并发送
    for i := 0; i < 10; i++ {
        fmt.Fprintf(w, "data: Message %d\n\n", i)
        flusher.Flush() // 立即将数据发送到客户端
        time.Sleep(time.Second) // 模拟处理时间
    }
}

func main() {
    http.HandleFunc("/stream", streamHandler)
    http.ListenAndServe(":8080", nil)
}

2. 前端 (JavaScript)

在前端,你可以使用 EventSource API 来接收服务器发送的事件。

<!DOCTYPE html>
<html>
<head>
    <title>Streaming Demo</title>
</head>
<body>
    <div id="output"></div>

    <script>
        const output = document.getElementById('output');
        const eventSource = new EventSource('/stream');

        eventSource.onmessage = function(event) {
            const p = document.createElement('p');
            p.textContent = event.data;
            output.appendChild(p);
        };

        eventSource.onerror = function(error) {
            console.error('EventSource failed:', error);
            eventSource.close();
        };
    </script>
</body>
</html>

3. 实际与模型交互

在实际应用中,你可能需要与特定的 AI 模型 API 进行交互。这里以 OpenAI 的 API 为例:

import (
    "context"
    "fmt"
    "io"
    "net/http"

    "github.com/sashabaranov/go-openai"
)

func streamHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
        return
    }

    client := openai.NewClient("your-api-key")
    ctx := context.Background()

    req := openai.CompletionRequest{
        Model:     openai.GPT3TextDavinci003,
        MaxTokens: 100,
        Prompt:    "Tell me a story",
        Stream:    true,
    }

    stream, err := client.CreateCompletionStream(ctx, req)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    defer stream.Close()

    for {
        response, err := stream.Recv()
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Fprintf(w, "data: Error: %v\n\n", err)
            flusher.Flush()
            break
        }

        fmt.Fprintf(w, "data: %s\n\n", response.Choices[0].Text)
        flusher.Flush()
    }
}

这个例子使用了 github.com/sashabaranov/go-openai 库来与 OpenAI API 交互。你需要替换 "your-api-key" 为你的实际 API 密钥。

go-zero 框架下的流式输出实现

以下是如何在 go-zero 框架下实现流式输出的步骤。

1. 定义新的路由

首先,在你的 api 文件中定义新的路由:

service stream-api {
    @handler StreamHandler
    get /stream
}

2. 实现 StreamHandler

然后,在你的 handler 文件中实现 StreamHandler:

package handler

import (
    "net/http"
    "github.com/zeromicro/go-zero/rest/httpx"
    "github.com/sashabaranov/go-openai"
    "context"
    "fmt"
    "io"
)

func StreamHandler(w http.ResponseWriter, r *http.Request) {
    // 设置响应头
    w.Header().Set("Content-Type", "text/event-stream")
    w.Header().Set("Cache-Control", "no-cache")
    w.Header().Set("Connection", "keep-alive")

    flusher, ok := w.(http.Flusher)
    if !ok {
        http.Error(w, "Streaming unsupported!", http.StatusInternalServerError)
        return
    }

    client := openai.NewClient("your-api-key")
    ctx := context.Background()

    req := openai.CompletionRequest{
        Model:     openai.GPT3TextDavinci003,
        MaxTokens: 100,
        Prompt:    "Tell me a story",
        Stream:    true,
    }

    stream, err := client.CreateCompletionStream(ctx, req)
    if err != nil {
        httpx.Error(w, err)
        return
    }
    defer stream.Close()

    for {
        response, err := stream.Recv()
        if err == io.EOF {
            break
        }
        if err != nil {
            fmt.Fprintf(w, "data: Error: %v\n\n", err)
            flusher.Flush()
            break
        }

        fmt.Fprintf(w, "data: %s\n\n", response.Choices[0].Text)
        flusher.Flush()
    }
}

3. 注册新的 handler

在你的 routes.go 文件中注册这个新的 handler:

package handler

import (
    "net/http"

    "github.com/zeromicro/go-zero/rest"
)

func RegisterHandlers(server *rest.Server) {
    server.AddRoutes(
        []rest.Route{
            {
                Method:  http.MethodGet,
                Path:    "/stream",
                Handler: StreamHandler,
            },
        },
    )
}

4. 前端代码保持不变

<!DOCTYPE html>
<html>
<head>
    <title>Streaming Demo</title>
</head>
<body>
    <div id="output"></div>

    <script>
        const output = document.getElementById('output');
        const eventSource = new EventSource('/stream');

        eventSource.onmessage = function(event) {
            const p = document.createElement('p');
            p.textContent = event.data;
            output.appendChild(p);
        };

        eventSource.onerror = function(error) {
            console.error('EventSource failed:', error);
            eventSource.close();
        };
    </script>
</body>
</html>

这样,你就可以在 go-zero 框架中实现流式输出了。记住要替换 "your-api-key" 为你的实际 OpenAI API 密钥。

标签:Set,http,stream,err,Header,zero,go,vllm
From: https://www.cnblogs.com/lwhzj/p/18347541

相关文章

  • 第五代英特尔® 至强® 可扩展处理器: PK8072205560、PK8072205560x00 Gold 处理器可实
    至强®可扩展处理器:第五代英特尔®至强®可扩展处理器采用内置英特尔®AIEngines,并具有与上一代相同的功率范围、软件和平台兼容性,可实现无与伦比的CPUAI性能。介绍英特尔®至强®Gold处理器英特尔®至强®Gold处理器针对要求严苛的AI、主流数据中心、多云计算......
  • 使用ansible安装mongodb分片集群
    【说明】使用ansible安装一个分片集群,三台服务器,三个mongos,三个config,三个分片节点,每三个分片有三个副本(每个节点运行三个端口的mongod)  [mongo_servers]10.x.x.21ansible_user=rootansible_ssh_pass=xxxxxxxxcluster_role=mongo1......
  • 腾讯云AI代码助手评测:如何智能高效完成Go语言Web项目开发
    腾讯云AI代码助手评测:如何智能高效完成Go语言Web项目开发......
  • go高并发之路——消息中间件kafka(下)
    一、kafka副本机制所谓的副本机制(Replication),也可以称之为备份机制,通常是指分布式系统在多台网络互联的机器上保存有相同的数据拷贝。kafka的副本概念实际上是在分区(partition)层级下定义的,每个分区配置有若干个副本。根据Kafka副本机制的定义,同一个分区下的所有副本保存有相同......
  • 通过go自定义alertmanager 发送通知的webhook
    本文主要是大体介绍webhook的代码以及涉及到的服务部署,详细配置需要自己弄Prometheus、alertmanager部署先创建alertmanager、Prometheus的docker-composeyaml文件,下面只是把服务运行起来,具体功能需要自己配置,如果有就跳过version:'3'services:prometheus:ima......
  • 基于django+vue的小说阅读系统【开题报告+程序+论文】-计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着互联网技术的飞速发展,数字阅读已成为人们获取信息与娱乐的重要方式之一。小说作为文学的重要分支,拥有庞大的读者群体。然而,传统的小说......
  • 基于django+vue的小区物业管理系统【开题报告+程序+论文】-计算机毕设
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表开题报告内容研究背景随着城市化进程的加速,住宅小区作为城市居民生活的重要载体,其管理与服务水平直接影响到居民的生活质量和幸福感。传统的物业管理方式往往依......
  • 部署argo-rollouts
    https://github.com/argoproj/argo-rollouts/releaseskubectlcreatenamespaceargo-rolloutskubectlapply-nargo-rollouts-fhttps://github.com/argoproj/argo-rollouts/releases/download/v1.3.1/install.yamlkubectlapply-fhttps://github.com/argoproj/argo-r......
  • ssh 远程登录报错:Unable to negotiate with IP port 22: no matching host key type f
    最近在Mac上想要远程一台Linux服务器,结果不知怎么的就不能使用以前的ssh登录了iot@ios-iMac~%[email protected]:nomatchinghostkeytypefound.Theiroffer:ssh-rsa,ssh-dss ......
  • go开发要不要拆分独立的包
    在Go语言中,业务开发时是否使用独立的Go包(package)主要取决于项目的结构和需求。以下是使用独立Go包的一些区别和考虑因素:1. 模块化:独立的Go包有助于将代码分割成更小的、可管理的模块。这有助于提高代码的可读性和可维护性。2. 重用性:通过将功能封装在独立的包中,你可以......