Base
@ -7,9 +7,9 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
@ -66,28 +66,16 @@ func addOpenaiMessage(c *fiber.Ctx) error {
|
||||
return err
|
||||
}
|
||||
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
collection.InsertOne(context.Background(), bson.M{"message": message, "role": "user", "date": time.Now()})
|
||||
|
||||
// Render bot message MAYBE to optimize
|
||||
// HOW TO GET STRING OF HTML FROM TEMPLATE
|
||||
tmpl, err := template.ParseFiles("views/partials/bot-message.gohtml")
|
||||
Content := chatCompletion.Choices[0].Message.Content
|
||||
out, err := botTmpl.Execute(pongo2.Context{"Content": Content})
|
||||
if err != nil {
|
||||
fmt.Println("Error parsing template:", err)
|
||||
return err
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Add bot message if there is no error
|
||||
var renderedMessage bytes.Buffer
|
||||
Message := chatCompletion.Choices[0].Message
|
||||
if err := tmpl.Execute(&renderedMessage, Message); err != nil {
|
||||
fmt.Println("Error rendering template:", err)
|
||||
return err
|
||||
}
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
collection.InsertOne(context.Background(), bson.M{"message": Content, "role": "bot", "date": time.Now()})
|
||||
|
||||
collection.InsertOne(context.Background(), bson.M{"message": Message.Content, "role": "bot", "date": time.Now()})
|
||||
|
||||
return c.SendString(renderedMessage.String())
|
||||
return c.SendString(out)
|
||||
}
|
||||
|
||||
func Message2OpenaiMessage(message Message) OpenaiMessage {
|
||||
|
@ -260,11 +260,11 @@ Well it do was pretty easy. I first did a base.html and then added an navbar and
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.user-message {
|
||||
.message-user {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.bot-message {
|
||||
.message-bot {
|
||||
align-self: flex-end;
|
||||
}
|
||||
</style>
|
||||
@ -284,7 +284,7 @@ The HTML at /chat/messages look like:
|
||||
<div class="column" id="messages">
|
||||
{% for message in messages %}
|
||||
{% if message.Role == 'user' %}
|
||||
<article class="message user-message" id='{{ message.id }}'>
|
||||
<article class="message message-user" id='{{ message.id }}'>
|
||||
<div class="message-header">
|
||||
<p>User</p>
|
||||
<form hx-delete="/chat" hx-swap="outerHTML" hx-target="#messages">
|
||||
@ -297,7 +297,7 @@ The HTML at /chat/messages look like:
|
||||
</div>
|
||||
</article>
|
||||
{% else %}
|
||||
<article class="message bot-message" id='{{ message.id }}'>
|
||||
<article class="message message-bot" id='{{ message.id }}'>
|
||||
<div class="message-header">
|
||||
<p>Bot</p>
|
||||
<form hx-delete="/chat" hx-swap="outerHTML" hx-target="#messages">
|
||||
|
26
edgedb.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/edgedb/edgedb-go"
|
||||
)
|
||||
|
||||
func main2() {
|
||||
ctx := context.Background()
|
||||
client, err := edgedb.CreateClient(ctx, edgedb.Options{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
var result string
|
||||
err = client.QuerySingle(ctx, "SELECT 'hello EdgeDB!'", &result)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(result)
|
||||
}
|
11
go.mod
@ -6,9 +6,12 @@ require (
|
||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||
github.com/bytedance/sonic v1.11.5 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/cloudwego/base64x v0.1.3 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/edgedb/edgedb-go v0.17.1 // indirect
|
||||
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 // indirect
|
||||
github.com/flosch/pongo2/v6 v6.0.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
@ -36,6 +39,7 @@ require (
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
@ -44,14 +48,19 @@ require (
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/xdg/scram v1.0.5 // indirect
|
||||
github.com/xdg/stringprep v1.0.3 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect
|
||||
go.mongodb.org/mongo-driver v1.15.0 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/net v0.24.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sync v0.2.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.9.3 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
24
go.sum
@ -7,6 +7,8 @@ github.com/bytedance/sonic v1.11.5/go.mod h1:X2PC2giUdj/Cv2lliWFLk6c/DUQok5rViJS
|
||||
github.com/bytedance/sonic/loader v0.1.0/go.mod h1:UmRT+IRTGKz/DAkzcEGzyVqQFJ7H9BqwBO3pm9H/+HY=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d h1:S2NE3iHSwP0XV47EEXL8mWmRdEfGscSJ+7EgePNgt0s=
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
|
||||
@ -18,6 +20,10 @@ github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/edgedb/edgedb-go v0.17.1 h1:nWVNWq61X1KyJziy5Zm+NfUwr7nXiCW7/qmH1zMSOpI=
|
||||
github.com/edgedb/edgedb-go v0.17.1/go.mod h1:J+llluepGAi/rIPNcUgIFEedCCISLKFG+VUEWnBhIqE=
|
||||
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3 h1:fmFk0Wt3bBxxwZnu48jqMdaOR/IZ4vdtJFuaFV8MpIE=
|
||||
github.com/flosch/pongo2 v0.0.0-20200913210552-0d938eb266f3/go.mod h1:bJWSKrZyQvfTnb2OudyUjurSG4/edverV7n82+K3JiM=
|
||||
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
|
||||
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
@ -59,6 +65,8 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
@ -75,11 +83,14 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg=
|
||||
github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3 h1:aQKxg3+2p+IFXXg97McgDGT5zcMrQoi0EICZs8Pgchs=
|
||||
github.com/sigurn/crc16 v0.0.0-20211026045750-20ab5afb07e3/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@ -107,6 +118,10 @@ github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
|
||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
|
||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xdg/scram v1.0.5 h1:TuS0RFmt5Is5qm9Tm2SoD89OPqe4IRiFtyFY4iwWXsw=
|
||||
github.com/xdg/scram v1.0.5/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||
github.com/xdg/stringprep v1.0.3 h1:cmL5Enob4W83ti/ZHuZLuKD/xqJfus4fVPwE+/BDm+4=
|
||||
github.com/xdg/stringprep v1.0.3/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
@ -119,7 +134,11 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea h1:vLCWI/yYrdEHyN2JzIzPO3aaQJHQdp89IZBA/+azVC4=
|
||||
golang.org/x/exp v0.0.0-20230510235704-dd950f8aeaea/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
@ -129,6 +148,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@ -150,11 +171,14 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
99
main.go
@ -1,15 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"github.com/gofiber/fiber/v2/middleware/logger"
|
||||
"github.com/gofiber/template/django/v3"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
@ -17,6 +15,8 @@ import (
|
||||
)
|
||||
|
||||
var mongoClient *mongo.Client
|
||||
var userTmpl *pongo2.Template
|
||||
var botTmpl *pongo2.Template
|
||||
|
||||
type Message struct {
|
||||
ID primitive.ObjectID `bson:"_id"`
|
||||
@ -58,6 +58,9 @@ func connectToMongoDB(uri string) {
|
||||
}
|
||||
|
||||
func main() {
|
||||
botTmpl = pongo2.Must(pongo2.FromFile("views/partials/message-bot.html"))
|
||||
userTmpl = pongo2.Must(pongo2.FromFile("views/partials/message-user.html"))
|
||||
|
||||
// Import HTML using django engine/template
|
||||
engine := django.New("./views", ".html")
|
||||
|
||||
@ -92,9 +95,6 @@ func main() {
|
||||
|
||||
app.Get("/generateOpenai", addOpenaiMessage)
|
||||
|
||||
app.Get("/sse", sseHandler) // SSE handler
|
||||
|
||||
// Add test button
|
||||
app.Get("/test-button", testButtonHandler)
|
||||
|
||||
// Start server
|
||||
@ -119,14 +119,21 @@ func addMessageHandler(c *fiber.Ctx) error {
|
||||
message := c.FormValue("message")
|
||||
lastMessageAsked = message
|
||||
|
||||
return c.Render("partials/user-message", fiber.Map{
|
||||
"Message": Message{
|
||||
Content: message,
|
||||
Role: "user",
|
||||
Date: time.Now(),
|
||||
},
|
||||
"IncludePlaceholder": true,
|
||||
})
|
||||
// Add bot message if there is no error
|
||||
userOut, err := userTmpl.Execute(pongo2.Context{"Content": message})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Content": "Waiting...", "IsPlaceholder": true})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
collection.InsertOne(context.Background(), bson.M{"message": message, "role": "user", "date": time.Now()})
|
||||
|
||||
return c.SendString(userOut + botOut)
|
||||
}
|
||||
|
||||
func deleteMessageHandler(c *fiber.Ctx) error {
|
||||
@ -195,11 +202,28 @@ func generateChatHTML(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
htmlString := "<div class='columns is-centered'><div class='column is-half' id='chat-messages'>"
|
||||
|
||||
for message := range Messages {
|
||||
if Messages[message].Role == "user" {
|
||||
userOut, err := userTmpl.Execute(pongo2.Context{"Content": Messages[message].Content})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
htmlString += userOut
|
||||
} else {
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Content": Messages[message].Content})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
htmlString += botOut
|
||||
}
|
||||
}
|
||||
|
||||
htmlString += "</div></div>"
|
||||
|
||||
// Render the HTML template with the messages
|
||||
return c.Render("partials/chat-messages", fiber.Map{
|
||||
"Messages": Messages,
|
||||
"IncludePlaceholder": false,
|
||||
})
|
||||
return c.SendString(htmlString)
|
||||
}
|
||||
|
||||
func isMongoDBConnectedHandler(c *fiber.Ctx) error {
|
||||
@ -208,42 +232,3 @@ func isMongoDBConnectedHandler(c *fiber.Ctx) error {
|
||||
}
|
||||
return c.SendString("<h1 hx-get='/isMongoDBConnected' hx-trigger='every 1s' hx-swap='outerHTM'>Not connected</h1>")
|
||||
}
|
||||
|
||||
// SSE Stuff
|
||||
var (
|
||||
eventChannel = make(chan string)
|
||||
)
|
||||
|
||||
func sseHandler(c *fiber.Ctx) error {
|
||||
c.Set("Content-Type", "text/event-stream")
|
||||
c.Set("Cache-Control", "no-cache")
|
||||
c.Set("Connection", "keep-alive")
|
||||
c.Set("Transfer-Encoding", "chunked")
|
||||
|
||||
c.Context().SetBodyStreamWriter(fasthttp.StreamWriter(func(w *bufio.Writer) {
|
||||
fmt.Println("WRITER")
|
||||
for {
|
||||
select {
|
||||
case msg := <-eventChannel:
|
||||
fmt.Fprintf(w, "data: %s\n\n", msg)
|
||||
err := w.Flush()
|
||||
if err != nil {
|
||||
fmt.Printf("Error while flushing: %v. Closing http connection.\n", err)
|
||||
return
|
||||
}
|
||||
default:
|
||||
if c.Context() != nil && c.Context().Done() != nil {
|
||||
select {
|
||||
case <-c.Context().Done():
|
||||
fmt.Println("Client connection closed")
|
||||
return
|
||||
default:
|
||||
}
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
BIN
static/icons/anthropic.png
Normal file
After Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 169 KiB After Width: | Height: | Size: 169 KiB |
BIN
static/icons/github.png
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
static/icons/huggingface.png
Normal file
After Width: | Height: | Size: 84 KiB |
BIN
static/icons/mistral.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
static/icons/openai.png
Normal file
After Width: | Height: | Size: 40 KiB |
37
static/puff.svg
Normal file
@ -0,0 +1,37 @@
|
||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<svg width="44" height="44" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="#fff">
|
||||
<g fill="none" fill-rule="evenodd" stroke-width="2">
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r"
|
||||
begin="0s" dur="1.8s"
|
||||
values="1; 20"
|
||||
calcMode="spline"
|
||||
keyTimes="0; 1"
|
||||
keySplines="0.165, 0.84, 0.44, 1"
|
||||
repeatCount="indefinite" />
|
||||
<animate attributeName="stroke-opacity"
|
||||
begin="0s" dur="1.8s"
|
||||
values="1; 0"
|
||||
calcMode="spline"
|
||||
keyTimes="0; 1"
|
||||
keySplines="0.3, 0.61, 0.355, 1"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="22" cy="22" r="1">
|
||||
<animate attributeName="r"
|
||||
begin="-0.9s" dur="1.8s"
|
||||
values="1; 20"
|
||||
calcMode="spline"
|
||||
keyTimes="0; 1"
|
||||
keySplines="0.165, 0.84, 0.44, 1"
|
||||
repeatCount="indefinite" />
|
||||
<animate attributeName="stroke-opacity"
|
||||
begin="-0.9s" dur="1.8s"
|
||||
values="1; 0"
|
||||
calcMode="spline"
|
||||
keyTimes="0; 1"
|
||||
keySplines="0.3, 0.61, 0.355, 1"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.4 KiB |
@ -1,5 +1,12 @@
|
||||
<div class="chat-container">
|
||||
<h1 class="title is-1">Chat Page</h1>
|
||||
<div hx-get="/loadChat" hx-trigger="load" hx-swap="outerHTML"></div>
|
||||
{% include "partials/chat-input.html" %}
|
||||
|
||||
<div class="columns is-centered">
|
||||
<div class="column is-8">
|
||||
<form hx-put="/chat" hx-swap="beforeend" hx-target="#chat-messages">
|
||||
<input class="input mx-5" type="text" placeholder="Type your message here..." name="message" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -8,31 +8,24 @@
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css">
|
||||
</head>
|
||||
|
||||
<body hx-ext="sse" sse-connect="/sse">
|
||||
<body>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.11"></script>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.12/dist/ext/sse.js"></script>
|
||||
|
||||
{% include "partials/navbar.html" %}
|
||||
|
||||
{{embed}}
|
||||
|
||||
<style>
|
||||
.column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.my-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message {
|
||||
max-width: 90%;
|
||||
margin-bottom: 10px;
|
||||
.htmx-request .my-indicator {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.user-message {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
.bot-message {
|
||||
align-self: flex-end;
|
||||
.htmx-request.my-indicator {
|
||||
display: inline;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -1,13 +0,0 @@
|
||||
<article class="message bot-message" id="bot-message-placeholder" hx-trigger="load" hx-swap="outerHTML"
|
||||
hx-get="/generateOpenai" hx-target="#bot-message-placeholder">
|
||||
<div class="message-header">
|
||||
<p>Bot</p>
|
||||
<form>
|
||||
<input type="hidden">
|
||||
<button class="delete" aria-label="delete"></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
Waiting...
|
||||
</div>
|
||||
</article>
|
@ -1,12 +0,0 @@
|
||||
<article class="message bot-message">
|
||||
<div class="message-header">
|
||||
<p>Bot</p>
|
||||
<form>
|
||||
<input type="hidden">
|
||||
<button class="delete" aria-label="delete"></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</article>
|
@ -1,12 +0,0 @@
|
||||
<article class="message bot-message">
|
||||
<div class="message-header">
|
||||
<p>Bot</p>
|
||||
<form>
|
||||
<input type="hidden">
|
||||
<button class="delete" aria-label="delete"></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
{{ Message.Content }}
|
||||
</div>
|
||||
</article>
|
@ -1,3 +0,0 @@
|
||||
<form hx-put="/chat" hx-swap="beforeend" hx-target="#chat-messages">
|
||||
<input class="input" type="text" placeholder="Type your message here..." name="message" />
|
||||
</form>
|
@ -1,11 +0,0 @@
|
||||
<div class="columns is-centered" hx-trigger="sse:bot-message" hx-swap="beforeend" hx-target="#chat-messages">
|
||||
<div class="column is-half" id="chat-messages">
|
||||
{% for Message in Messages %}
|
||||
{% if Message.Role == "user" %}
|
||||
{% include "partials/user-message.html" %}
|
||||
{% else %}
|
||||
{% include "partials/bot-message.html" %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
22
views/partials/message-bot.html
Normal file
@ -0,0 +1,22 @@
|
||||
<div class="message-user mt-3" style="display: flex; align-items: flex-start;" {% if IsPlaceholder %}
|
||||
hx-get="/generateOpenai" hx-trigger="load" hx-swap="outerHTML" hx-indicator="#spinner" {% endif %}>
|
||||
<figure class="image is-48x48 mr-2" style="flex-shrink: 0;">
|
||||
<img src="icons/openai.png" alt="User Image">
|
||||
</figure>
|
||||
<article class="message">
|
||||
<div class="message-header">
|
||||
<p>User</p>
|
||||
<form>
|
||||
<input type="hidden">
|
||||
<button class="delete" aria-label="delete"></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
{% if IsPlaceholder %}
|
||||
<img id="spinner" class="htmx-indicator" src="/puff.svg" />
|
||||
{% else %}
|
||||
{{ Content }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
17
views/partials/message-user.html
Normal file
@ -0,0 +1,17 @@
|
||||
<div class="message-user mt-3" style="display: flex; align-items: flex-start;">
|
||||
<figure class="image is-48x48 mr-2" style="flex-shrink: 0;">
|
||||
<img src="icons/huggingface.png" alt="User Image">
|
||||
</figure>
|
||||
<article class="message">
|
||||
<div class="message-header">
|
||||
<p>User</p>
|
||||
<form>
|
||||
<input type="hidden">
|
||||
<button class="delete" aria-label="delete"></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
{{ Content }}
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
@ -1,7 +1,7 @@
|
||||
<nav class="navbar is-primary">
|
||||
<div class="navbar-brand">
|
||||
<a class="navbar-item" href="https://www.bouvai.com">
|
||||
<img src="/bouvai.png">
|
||||
<img src="/icons/bouvai.png">
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-menu">
|
||||
|
@ -1 +0,0 @@
|
||||
<button class="button is-primary" hx-get="/test-button" hx-swap="outerHTML">Test</button>
|
@ -1 +0,0 @@
|
||||
<p sse-swap="test">Test</p>
|
@ -1,15 +0,0 @@
|
||||
<article class="message user-message">
|
||||
<div class="message-header">
|
||||
<p>User</p>
|
||||
<form>
|
||||
<input type="hidden">
|
||||
<button class="delete" aria-label="delete"></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="message-body">
|
||||
{{ Message.Content }}
|
||||
</div>
|
||||
</article>
|
||||
{% if IncludePlaceholder %}
|
||||
{% include "partials/bot-message-placeholder.html" %}
|
||||
{% endif %}
|
@ -2,7 +2,5 @@
|
||||
<div class="column">
|
||||
<h1 class="title is-1">Welcome to JADE 2.0!</h1>
|
||||
<h1 hx-get="/isMongoDBConnected" hx-trigger="load" hx-swap="outerHTML"></h1>
|
||||
{% include "partials/test-display.html" %}
|
||||
{% include "partials/test-button.html" %}
|
||||
</div>
|
||||
</div>
|