美文网首页
2023-02-15 用go gin 简单接入gpt3 stre

2023-02-15 用go gin 简单接入gpt3 stre

作者: 江江江123 | 来源:发表于2023-02-14 18:49 被阅读0次

核心知识点:

gin 加载html
chat gpt Stream
gin stream
js EventSource

关于gpt3中的上下文:

只要将之前的问题和回答用换行符号拼接 最后再加新的的问题即可

关于参数MaxTokens:

返回最大文本数,openai 也是基于这个参数收费

源码:

用html简单写个简易前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="result">

</div>

<div>
    <input type="text" id="msg">
    <button type="button" onclick="submit()">提交!</button>
</div>
</body>
<script>
    class Chat {
        constructor(q, a) {
            this.q = q;
            this.a = a;
        }
    }

    const chats = [];

    function submit() {
        let question = document.getElementById("msg").value
        if (question === undefined || question === "") {
            alert("please input question")
        }
        const chat = new Chat();
        chat.q = question;
        chat.a = "";
        const stream = new EventSource("/stream?msg=" + chat.q + "&chats=" + JSON.stringify(chats))
        stream.addEventListener("message", function (e) {
            let parse = JSON.parse(e.data);
            chat.a += parse["text"]
            document.getElementById("result").innerHTML = chat.a
        });
        stream.addEventListener("stop", function (e) {
            stream.close()
            chat.a += "\n"
            chats.push(chat)
            document.getElementById("result").innerHTML = chat.a
            console.log(e)
        });
        stream.onerror = function (event) {
            stream.close()
            console.log(event)
        }
    }

</script>
</html>

go

gin提供服务
go-gp3 调用openai接口

package main

import (
    "context"
    "encoding/json"
    "errors"
    "fmt"
    "github.com/gin-gonic/gin"
    gogpt "github.com/sashabaranov/go-gpt3"
    "io"
    "log"
    "net/http"
    "os"
    "os/signal"
    "time"
)
type SteamRequest struct {
    Msg   string `form:"msg" binding:"required"`
    Chats string `form:"chats" binding:"required"`
}
type Chat struct {
    A string `form:"a"`
    Q string `form:"q"`
}

func setupRouter() *gin.Engine {
    r := gin.Default()
    r.LoadHTMLGlob("templates/*")
    r.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.html", gin.H{
            "title": "Main website",
        })
    })
    
    r.GET("/stream", func(c *gin.Context) {
        var request SteamRequest
        err := c.ShouldBindQuery(&request)
        if err != nil {
            log.Fatal(err.Error())
        }
        log.Println("request" + request.Msg)
        var chats []Chat
        errs := json.Unmarshal([]byte(request.Chats), &chats)
        if errs != nil {
            fmt.Println("json unmarshal error:", errs)
        }
        var question = ""
        if len(chats) != 0 {
            for i := 0; i < len(chats); i++ {
                chat := chats[i]
                question += chat.Q + "\n" + chat.A
            }
        }
        question += request.Msg

        client := gogpt.NewClient("you token")
        ctx := context.Background()

        req := gogpt.CompletionRequest{
            Model:     gogpt.GPT3TextDavinci003,
            MaxTokens: 5,
            Prompt:    question,
            Stream:    true,
        }
        stream, err := client.CreateCompletionStream(ctx, req)
        if err != nil {
            return
        }

        chanStream := make(chan string, 100)
        go func() {
            defer stream.Close()
            defer close(chanStream)
            for {
                response, err := stream.Recv()
                if errors.Is(err, io.EOF) {
                    fmt.Println("Stream finished")
                    chanStream <- "<!finish>"
                    return
                }

                if err != nil {
                    fmt.Printf("Stream error: %v\n", err)
                    chanStream <- "<!error>"
                    return
                }
                if len(response.Choices) == 0 {
                    fmt.Println("Stream finished")
                    chanStream <- "<!finish>"
                    return
                }
                data, err := json.Marshal(response.Choices[0])
                chanStream <- string(data)
                fmt.Printf("Stream response: %v\n", response.Choices[0])
            }
        }()

        c.Stream(func(w io.Writer) bool {
            if msg, ok := <-chanStream; ok {
                if msg == "<!finish>" {
                    c.SSEvent("stop", "finish")
                }
                if msg == "<!error>" {
                    c.SSEvent("stop", "error")
                }
                c.SSEvent("message", msg)
                fmt.Printf("message: %v\n", msg)

                return true
            }
            return false
        })

    })
    return r
}

func main() {
    gin.SetMode(gin.ReleaseMode)
    router := setupRouter()
    srv := &http.Server{
        Addr:    ":8080",
        Handler: router,
    }
    go func() {
        // 服务连接
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("listen: %s\n", err)
        }
    }()

    // 等待中断信号以优雅地关闭服务器(设置 5 秒的超时时间)
    quit := make(chan os.Signal)
    signal.Notify(quit, os.Interrupt)
    <-quit
    log.Println("Shutdown Server ...")

    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server Shutdown:", err)
    }
    log.Println("Server exiting")
}

相关文章

网友评论

      本文标题:2023-02-15 用go gin 简单接入gpt3 stre

      本文链接:https://www.haomeiwen.com/subject/rsgekdtx.html