Edge transition
This commit is contained in:
parent
e433240939
commit
35ba12ae81
171
Chat.go
171
Chat.go
@ -3,32 +3,14 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"log"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/edgedb/edgedb-go"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
ID primitive.ObjectID `bson:"_id"`
|
||||
Content string `bson:"message"`
|
||||
Role string `bson:"role"`
|
||||
Date time.Time `bson:"date"`
|
||||
Model string `bson:"model"`
|
||||
Selected bool `bson:"selected"`
|
||||
LinkedMessageIds []string `bson:"linked_message_ids"`
|
||||
}
|
||||
|
||||
type Conversation struct {
|
||||
ID string
|
||||
Messages []Message
|
||||
}
|
||||
|
||||
func ChatPageHandler(c *fiber.Ctx) error {
|
||||
return c.Render("chat", fiber.Map{}, "layouts/main")
|
||||
}
|
||||
@ -47,55 +29,27 @@ func LoadModelSelectionHandler(c *fiber.Ctx) error {
|
||||
return c.SendString(out)
|
||||
}
|
||||
|
||||
func LoadConversationsSelectionHandler(c *fiber.Ctx) error {
|
||||
out, err := conversationsPopoverTmpl.Execute(pongo2.Context{
|
||||
"Conversations": "",
|
||||
})
|
||||
if err != nil {
|
||||
c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error rendering template",
|
||||
})
|
||||
}
|
||||
return c.SendString(out)
|
||||
}
|
||||
|
||||
func DeleteMessageHandler(c *fiber.Ctx) error {
|
||||
messageId := c.FormValue("id")
|
||||
|
||||
// messageId is a string that look like ObjectID("662d6556e5328bbc8357cfb1")
|
||||
// Get the message from the db and delete it and all messages after it
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
fmt.Println("Deleting message: " + messageId)
|
||||
|
||||
// Convert the messageId string to a bson.ObjectId
|
||||
objectID, err := primitive.ObjectIDFromHex(messageId)
|
||||
messageUUID, err := edgedb.ParseUUID(messageId)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid message ID",
|
||||
})
|
||||
fmt.Println("Error in uuid.FromString: in DeleteMessageHandler")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// Find the message with the given ID
|
||||
message := &Message{}
|
||||
err = collection.FindOne(c.Context(), bson.M{"_id": objectID}).Decode(message)
|
||||
// Delete all messages
|
||||
err = edgeClient.Execute(edgeCtx, `
|
||||
WITH
|
||||
messageArea := (SELECT Message FILTER .id = <uuid>$0).area
|
||||
DELETE Area
|
||||
FILTER .position >= messageArea.position AND .conversation = messageArea.conversation;
|
||||
`, messageUUID)
|
||||
if err != nil {
|
||||
if err == mongo.ErrNoDocuments {
|
||||
return c.Status(http.StatusNotFound).JSON(fiber.Map{
|
||||
"error": "Message not found",
|
||||
})
|
||||
}
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error finding message",
|
||||
})
|
||||
}
|
||||
|
||||
// Delete the message and all messages after it
|
||||
_, err = collection.DeleteMany(c.Context(), bson.M{
|
||||
"date": bson.M{"$gte": message.Date},
|
||||
})
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error deleting messages",
|
||||
})
|
||||
fmt.Println("Error in edgeClient.Execute: in DeleteMessageHandler")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
return c.SendString(generateChatHTML())
|
||||
@ -105,44 +59,6 @@ func LoadChatHandler(c *fiber.Ctx) error {
|
||||
return c.SendString(generateChatHTML())
|
||||
}
|
||||
|
||||
func ChangeSelectedMessageHandler(c *fiber.Ctx) error {
|
||||
messageId := c.FormValue("id")
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
objectID, err := primitive.ObjectIDFromHex(messageId)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid message ID",
|
||||
})
|
||||
}
|
||||
|
||||
var selectedMessage Message
|
||||
err = collection.FindOne(c.Context(), bson.M{"_id": objectID}).Decode(&selectedMessage)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error finding message",
|
||||
})
|
||||
}
|
||||
|
||||
for i := range selectedMessage.LinkedMessageIds {
|
||||
objectID, _ = primitive.ObjectIDFromHex(selectedMessage.LinkedMessageIds[i])
|
||||
_, err = collection.UpdateOne(c.Context(), bson.M{"_id": objectID}, bson.M{"$set": bson.M{"selected": false}})
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error updating message",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
_, err = collection.UpdateOne(c.Context(), bson.M{"_id": objectID}, bson.M{"$set": bson.M{"selected": true}})
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error updating message",
|
||||
})
|
||||
}
|
||||
|
||||
return c.SendString(generateChatHTML())
|
||||
}
|
||||
|
||||
type NextMessage struct {
|
||||
Icon string
|
||||
Content string
|
||||
@ -153,19 +69,7 @@ type NextMessage struct {
|
||||
|
||||
func generateChatHTML() string {
|
||||
// Get the messages from the database
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
|
||||
// Get all messages
|
||||
cursor, err := collection.Find(context.TODO(), bson.D{})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
// Convert the cursor to an array of messages
|
||||
var Messages []Message
|
||||
if err = cursor.All(context.TODO(), &Messages); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
Messages := getAllMessages()
|
||||
|
||||
htmlString := "<div class='columns is-centered' id='chat-container'><div class='column is-12-mobile is-8-tablet is-6-desktop' id='chat-messages'>"
|
||||
|
||||
@ -174,7 +78,7 @@ func generateChatHTML() string {
|
||||
for i, message := range Messages {
|
||||
if message.Role == "user" {
|
||||
htmlContent := markdownToHTML(message.Content)
|
||||
userOut, err := userTmpl.Execute(pongo2.Context{"Content": htmlContent, "ID": message.ID.Hex()})
|
||||
userOut, err := userTmpl.Execute(pongo2.Context{"Content": htmlContent, "ID": message.ID.String()})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
@ -183,13 +87,21 @@ func generateChatHTML() string {
|
||||
NextMessages = []NextMessage{}
|
||||
} else {
|
||||
fmt.Println(i)
|
||||
modelID, exist := message.ModelID.Get()
|
||||
if !exist {
|
||||
modelID = "gpt-3.5-turbo"
|
||||
}
|
||||
selected, exist := message.Selected.Get()
|
||||
if !exist {
|
||||
selected = false
|
||||
}
|
||||
// For bot messages, add them to NextMessages with only the needed fields
|
||||
nextMsg := NextMessage{
|
||||
Icon: model2Icon(message.Model), // Assuming Icon is a field you want to include from Message
|
||||
Icon: model2Icon(modelID), // Assuming Icon is a field you want to include from Message
|
||||
Content: markdownToHTML(message.Content),
|
||||
Hidden: !message.Selected, // Assuming Hidden is a field you want to include from Message
|
||||
Id: message.ID.Hex(),
|
||||
Name: model2Name(message.Model),
|
||||
Hidden: !selected, // Assuming Hidden is a field you want to include from Message
|
||||
Id: message.ID.String(),
|
||||
Name: model2Name(modelID),
|
||||
}
|
||||
NextMessages = append(NextMessages, nextMsg)
|
||||
|
||||
@ -224,25 +136,30 @@ func generateChatHTML() string {
|
||||
func GetMessageContentHandler(c *fiber.Ctx) error {
|
||||
messageId := c.FormValue("id")
|
||||
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
objectID, err := primitive.ObjectIDFromHex(messageId)
|
||||
messageUUID, err := edgedb.ParseUUID(messageId)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusBadRequest).JSON(fiber.Map{
|
||||
"error": "Invalid message ID",
|
||||
})
|
||||
fmt.Println("Error in uuid.FromString: in DeleteMessageHandler")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
var selectedMessage Message
|
||||
err = collection.FindOne(c.Context(), bson.M{"_id": objectID}).Decode(&selectedMessage)
|
||||
err = edgeClient.QuerySingle(context.Background(), `
|
||||
SELECT Message {
|
||||
model_id,
|
||||
content
|
||||
}
|
||||
FILTER
|
||||
.id = <uuid>$0;
|
||||
`, &selectedMessage, messageUUID)
|
||||
if err != nil {
|
||||
return c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error finding message",
|
||||
})
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
modelID, _ := selectedMessage.ModelID.Get()
|
||||
|
||||
out := "<div class='message-header'>"
|
||||
out += "<p>"
|
||||
out += model2Name(selectedMessage.Model)
|
||||
out += model2Name(modelID)
|
||||
out += " </p>"
|
||||
out += "</div>"
|
||||
out += "<div class='message-body'>"
|
||||
|
21
Request.go
21
Request.go
@ -1,14 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/edgedb/edgedb-go"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
type ModelInfo struct {
|
||||
@ -46,7 +43,7 @@ var lastSelectedModelIds []string
|
||||
func GenerateMultipleMessages(c *fiber.Ctx) error {
|
||||
// Create a wait group to synchronize the goroutines
|
||||
var wg sync.WaitGroup
|
||||
var InsertedIDs []string
|
||||
var InsertedIDs []edgedb.UUID
|
||||
|
||||
// Add the length of lastSelectedModelIds goroutines to the wait group
|
||||
wg.Add(len(lastSelectedModelIds))
|
||||
@ -70,12 +67,6 @@ func GenerateMultipleMessages(c *fiber.Ctx) error {
|
||||
// Wait for both goroutines to finish
|
||||
wg.Wait()
|
||||
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
for i := range InsertedIDs {
|
||||
objectID, _ := primitive.ObjectIDFromHex(InsertedIDs[i])
|
||||
collection.UpdateOne(context.Background(), bson.M{"_id": objectID}, bson.M{"$set": bson.M{"linked_message_ids": InsertedIDs}})
|
||||
}
|
||||
|
||||
return c.SendString(generateChatHTML())
|
||||
}
|
||||
|
||||
@ -85,8 +76,9 @@ func RequestMultipleMessages(c *fiber.Ctx) error {
|
||||
return c.SendString(chatString)
|
||||
}
|
||||
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
result, _ := collection.InsertOne(context.Background(), bson.M{"message": message, "role": "user", "date": time.Now()})
|
||||
// Add an Area with the user message inside
|
||||
insertArea()
|
||||
messageID := insertUserMessage(message)
|
||||
|
||||
selectedModelIds := []string{}
|
||||
for CompanyInfo := range CompanyInfos {
|
||||
@ -101,8 +93,7 @@ func RequestMultipleMessages(c *fiber.Ctx) error {
|
||||
|
||||
out := ""
|
||||
|
||||
HexID := result.InsertedID.(primitive.ObjectID).Hex()
|
||||
messageOut, _ := userTmpl.Execute(pongo2.Context{"Content": markdownToHTML(message), "ID": HexID})
|
||||
messageOut, _ := userTmpl.Execute(pongo2.Context{"Content": markdownToHTML(message), "ID": messageID.String()})
|
||||
out += messageOut
|
||||
|
||||
messageOut, _ = botTmpl.Execute(pongo2.Context{"IsPlaceholder": true, "SelectedModelIds": selectedModelIds, "Message": message})
|
||||
|
@ -2,15 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"github.com/edgedb/edgedb-go"
|
||||
)
|
||||
|
||||
type AnthropicChatCompletionRequest struct {
|
||||
@ -87,7 +84,7 @@ func init() {
|
||||
CompanyInfos = append(CompanyInfos, companyInfo)
|
||||
}
|
||||
|
||||
func addAnthropicMessage(modelID string, selected bool) string {
|
||||
func addAnthropicMessage(modelID string, selected bool) edgedb.UUID {
|
||||
Messages := getAllMessages()
|
||||
|
||||
chatCompletion, err := RequestAnthropic(modelID, Messages, 2048, 0.7) // TODO CHange parameters
|
||||
@ -97,25 +94,17 @@ func addAnthropicMessage(modelID string, selected bool) string {
|
||||
} else if len(chatCompletion.Content) == 0 {
|
||||
fmt.Println(chatCompletion)
|
||||
fmt.Println("No response from Anthropic")
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
response, err := collection.InsertOne(context.Background(), bson.M{"message": "no response", "role": "bot", "date": time.Now(), "model": modelID, "selected": selected})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return response.InsertedID.(primitive.ObjectID).Hex()
|
||||
id := insertBotMessage("No response from Anthropic", selected, modelID)
|
||||
return id
|
||||
} else {
|
||||
Content := chatCompletion.Content[0].Text
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
response, err := collection.InsertOne(context.Background(), bson.M{"message": Content, "role": "bot", "date": time.Now(), "model": modelID, "selected": selected})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return response.InsertedID.(primitive.ObjectID).Hex()
|
||||
id := insertBotMessage(Content, selected, modelID)
|
||||
return id
|
||||
}
|
||||
return ""
|
||||
return edgedb.UUID{}
|
||||
}
|
||||
|
||||
func Messages2AnthropicMessages(messages []Message) []AnthropicMessage {
|
||||
func EdgeMessages2AnthropicMessages(messages []Message) []AnthropicMessage {
|
||||
AnthropicMessages := make([]AnthropicMessage, len(messages))
|
||||
for i, msg := range messages {
|
||||
var role string
|
||||
@ -139,7 +128,7 @@ func RequestAnthropic(model string, messages []Message, maxTokens int, temperatu
|
||||
apiKey := "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" // TODO Use env variable
|
||||
url := "https://api.anthropic.com/v1/messages"
|
||||
|
||||
AnthropicMessages := Messages2AnthropicMessages(messages)
|
||||
AnthropicMessages := EdgeMessages2AnthropicMessages(messages)
|
||||
|
||||
requestBody := AnthropicChatCompletionRequest{
|
||||
Model: model,
|
||||
|
@ -2,15 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
"github.com/edgedb/edgedb-go"
|
||||
)
|
||||
|
||||
type OpenaiChatCompletionRequest struct {
|
||||
@ -79,7 +76,7 @@ func init() {
|
||||
CompanyInfos = append(CompanyInfos, companyInfo)
|
||||
}
|
||||
|
||||
func addOpenaiMessage(modelID string, selected bool) string {
|
||||
func addOpenaiMessage(modelID string, selected bool) edgedb.UUID {
|
||||
Messages := getAllMessages()
|
||||
|
||||
chatCompletion, err := RequestOpenai(modelID, Messages, 0.7)
|
||||
@ -88,25 +85,17 @@ func addOpenaiMessage(modelID string, selected bool) string {
|
||||
} else if len(chatCompletion.Choices) == 0 {
|
||||
fmt.Println(chatCompletion)
|
||||
fmt.Println("No response from OpenAI")
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
response, err := collection.InsertOne(context.Background(), bson.M{"message": "no response", "role": "bot", "date": time.Now(), "model": modelID, "selected": selected})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return response.InsertedID.(primitive.ObjectID).Hex()
|
||||
id := insertBotMessage("No response from OpenAI", selected, modelID)
|
||||
return id
|
||||
} else {
|
||||
Content := chatCompletion.Choices[0].Message.Content
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
response, err := collection.InsertOne(context.Background(), bson.M{"message": Content, "role": "bot", "date": time.Now(), "model": modelID, "selected": selected})
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return response.InsertedID.(primitive.ObjectID).Hex()
|
||||
id := insertBotMessage(Content, selected, modelID)
|
||||
return id
|
||||
}
|
||||
return ""
|
||||
return edgedb.UUID{}
|
||||
}
|
||||
|
||||
func Messages2OpenaiMessages(messages []Message) []OpenaiMessage {
|
||||
func EdgeMessages2OpenaiMessages(messages []Message) []OpenaiMessage {
|
||||
openaiMessages := make([]OpenaiMessage, len(messages))
|
||||
for i, msg := range messages {
|
||||
var role string
|
||||
@ -131,7 +120,7 @@ func RequestOpenai(model string, messages []Message, temperature float64) (Opena
|
||||
url := "https://api.openai.com/v1/chat/completions"
|
||||
|
||||
// Convert messages to OpenAI format
|
||||
openaiMessages := Messages2OpenaiMessages(messages)
|
||||
openaiMessages := EdgeMessages2OpenaiMessages(messages)
|
||||
|
||||
requestBody := OpenaiChatCompletionRequest{
|
||||
Model: model,
|
||||
|
@ -1,10 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
)
|
||||
|
||||
type Command struct {
|
||||
@ -26,13 +23,7 @@ func init() {
|
||||
}
|
||||
|
||||
func ClearCommandHandler(c *fiber.Ctx) string {
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
_, err := collection.DeleteMany(c.Context(), bson.D{})
|
||||
if err != nil {
|
||||
c.Status(http.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Failed to clear messages",
|
||||
})
|
||||
}
|
||||
// DOTO clear the chat
|
||||
return "<hx hx-get='/loadChat' hx-trigger='load' hx-swap='outerHTML' hx-target='#chat-container'></hx>"
|
||||
}
|
||||
|
||||
|
203
database.go
203
database.go
@ -3,38 +3,205 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"github.com/edgedb/edgedb-go"
|
||||
)
|
||||
|
||||
var mongoClient *mongo.Client
|
||||
var edgeCtx context.Context
|
||||
var edgeClient *edgedb.Client
|
||||
var CurrentUser User
|
||||
|
||||
type User struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Email string `edgedb:"email"`
|
||||
Name string `edgedb:"name"`
|
||||
Setting Setting `edgedb:"setting"`
|
||||
Conversations []Conversation `edgedb:"conversations"`
|
||||
Usages []Usage `edgedb:"usages"`
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Name string `edgedb:"name"`
|
||||
Key string `edgedb:"key"`
|
||||
Date time.Time `edgedb:"date"`
|
||||
}
|
||||
|
||||
type Setting struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Keys []Key `edgedb:"keys"`
|
||||
DefaultModel edgedb.OptionalStr `edgedb:"default_model"`
|
||||
}
|
||||
|
||||
type Conversation struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Name string `edgedb:"name"`
|
||||
Areas []Area `edgedb:"areas"`
|
||||
}
|
||||
|
||||
type Area struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Position int `edgedb:"position"`
|
||||
Messages []Message `edgedb:"messages"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
ModelID edgedb.OptionalStr `edgedb:"model_id"`
|
||||
Selected edgedb.OptionalBool `edgedb:"selected"`
|
||||
Role string `edgedb:"role"`
|
||||
Content string `edgedb:"content"`
|
||||
Date time.Time `edgedb:"date"`
|
||||
}
|
||||
|
||||
type Usage struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
ModelID string `edgedb:"model_id"`
|
||||
Date time.Time `edgedb:"date"`
|
||||
InputCost edgedb.OptionalFloat32 `edgedb:"input_cost"`
|
||||
OutputCost edgedb.OptionalFloat32 `edgedb:"output_cost"`
|
||||
InputToken edgedb.OptionalInt32 `edgedb:"input_token"`
|
||||
OutputToken edgedb.OptionalInt32 `edgedb:"output_token"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
serverAPI := options.ServerAPI(options.ServerAPIVersion1)
|
||||
opts := options.Client().ApplyURI("mongodb://localhost:27017").SetServerAPIOptions(serverAPI)
|
||||
client, err := mongo.Connect(context.TODO(), opts)
|
||||
var ctx = context.Background()
|
||||
client, err := edgedb.CreateClient(ctx, edgedb.Options{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
fmt.Println("Error in edgedb.CreateClient: in init")
|
||||
log.Fatal(err)
|
||||
}
|
||||
mongoClient = client
|
||||
|
||||
if err := mongoClient.Ping(context.TODO(), nil); err != nil {
|
||||
panic(err)
|
||||
// Get the user test@example.com
|
||||
var user User
|
||||
err = client.QuerySingle(ctx, `
|
||||
SELECT User { id, email, name, setting } FILTER .email = <str>$0 LIMIT 1
|
||||
`, &user, "test@example.com")
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in init")
|
||||
log.Fatal(err)
|
||||
}
|
||||
CurrentUser = user
|
||||
|
||||
fmt.Print("Current User: ")
|
||||
fmt.Println(CurrentUser)
|
||||
|
||||
edgeCtx = ctx
|
||||
edgeClient = client
|
||||
}
|
||||
|
||||
func getLastArea() edgedb.UUID {
|
||||
var inserted struct{ id edgedb.UUID }
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
select Area
|
||||
filter .conversation.name = 'Default' AND .conversation.user.id = <uuid>$0
|
||||
order by .position desc
|
||||
limit 1
|
||||
`, &inserted, CurrentUser.ID)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in getLastArea")
|
||||
log.Fatal(err)
|
||||
}
|
||||
return inserted.id
|
||||
}
|
||||
|
||||
func insertArea() edgedb.UUID {
|
||||
// Insert a new area.
|
||||
var inserted struct{ id edgedb.UUID }
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
WITH
|
||||
positionVar := count((SELECT Area FILTER .conversation.name = 'Default' AND .conversation.user.id = <uuid>$0)) + 1
|
||||
INSERT Area {
|
||||
position := positionVar,
|
||||
conversation := (
|
||||
SELECT Conversation
|
||||
FILTER .name = 'Default' AND .user.id = <uuid>$0
|
||||
LIMIT 1
|
||||
)
|
||||
}
|
||||
`, &inserted, CurrentUser.ID)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in insertArea")
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
return inserted.id
|
||||
}
|
||||
|
||||
func insertUserMessage(content string) edgedb.UUID {
|
||||
// Insert a new user.
|
||||
lastAreaID := getLastArea()
|
||||
var inserted struct{ id edgedb.UUID }
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
INSERT Message {
|
||||
role := <str>$0,
|
||||
content := <str>$1,
|
||||
area := (
|
||||
SELECT Area
|
||||
FILTER .id = <uuid>$2
|
||||
),
|
||||
conversation := (
|
||||
SELECT Conversation
|
||||
FILTER .name = 'Default' AND .user.id = <uuid>$3
|
||||
LIMIT 1
|
||||
)
|
||||
}
|
||||
`, &inserted, "user", content, lastAreaID, CurrentUser.ID)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in insertUserMessage")
|
||||
log.Fatal(err)
|
||||
}
|
||||
return inserted.id
|
||||
}
|
||||
|
||||
func insertBotMessage(content string, selected bool, model string) edgedb.UUID {
|
||||
lastAreaID := getLastArea()
|
||||
var inserted struct{ id edgedb.UUID }
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
INSERT Message {
|
||||
role := <str>$0,
|
||||
model_id := <str>$1,
|
||||
content := <str>$2,
|
||||
selected := <bool>$3,
|
||||
conversation := (
|
||||
SELECT Conversation
|
||||
FILTER .name = 'Default' AND .user.id = <uuid>$4
|
||||
LIMIT 1
|
||||
),
|
||||
area := (
|
||||
SELECT Area
|
||||
FILTER .id = <uuid>$5
|
||||
LIMIT 1
|
||||
)
|
||||
}
|
||||
`, &inserted, "bot", model, content, selected, CurrentUser.ID, lastAreaID)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in insertBotMessage")
|
||||
log.Fatal(err)
|
||||
}
|
||||
return inserted.id
|
||||
}
|
||||
|
||||
func getAllMessages() []Message {
|
||||
collection := mongoClient.Database("chat").Collection("messages")
|
||||
cursor, err := collection.Find(context.TODO(), bson.D{})
|
||||
var messages []Message
|
||||
|
||||
err := edgeClient.Query(edgeCtx, `
|
||||
SELECT Message {
|
||||
id,
|
||||
model_id,
|
||||
selected,
|
||||
role,
|
||||
content,
|
||||
date
|
||||
} FILTER .conversation.name = 'Default' AND .conversation.user.id = <uuid>$0
|
||||
ORDER BY .date ASC
|
||||
`, &messages, CurrentUser.ID)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.Query: in getAllMessages")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
var Messages []Message
|
||||
if err = cursor.All(context.TODO(), &Messages); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
return Messages
|
||||
return messages
|
||||
}
|
||||
|
64
dbschema/default.esdl
Normal file
64
dbschema/default.esdl
Normal file
@ -0,0 +1,64 @@
|
||||
module default {
|
||||
type User {
|
||||
required email: str;
|
||||
required name: str;
|
||||
required setting: Setting;
|
||||
}
|
||||
|
||||
type Key {
|
||||
required name: str;
|
||||
required company: str;
|
||||
required key: str;
|
||||
required date: datetime {
|
||||
default := datetime_current();
|
||||
}
|
||||
}
|
||||
|
||||
type Setting {
|
||||
default_model: str;
|
||||
multi keys: Key;
|
||||
}
|
||||
|
||||
type Conversation {
|
||||
required name: str;
|
||||
required user: User {
|
||||
on target delete delete source;
|
||||
};
|
||||
required date: datetime {
|
||||
default := datetime_current();
|
||||
}
|
||||
}
|
||||
|
||||
type Area {
|
||||
required position: int64;
|
||||
required conversation: Conversation {
|
||||
on target delete delete source;
|
||||
};
|
||||
}
|
||||
|
||||
type Message {
|
||||
model_id: str;
|
||||
selected: bool;
|
||||
required role: str;
|
||||
required content: str;
|
||||
required area: Area {
|
||||
on target delete delete source;
|
||||
};
|
||||
required conversation: Conversation;
|
||||
required date: datetime {
|
||||
default := datetime_current();
|
||||
}
|
||||
}
|
||||
|
||||
type Usage {
|
||||
required model_id: str;
|
||||
required user: User;
|
||||
input_cost: float32;
|
||||
output_cost: float32;
|
||||
input_token: int32;
|
||||
output_token: int32;
|
||||
required date: datetime {
|
||||
default := datetime_current();
|
||||
}
|
||||
}
|
||||
}
|
41
dbschema/migrations/00001-m1oqsdj.edgeql
Normal file
41
dbschema/migrations/00001-m1oqsdj.edgeql
Normal file
@ -0,0 +1,41 @@
|
||||
CREATE MIGRATION m1oqsdj6bfa6gqquonw63gm53g6zo2uf2cjicsjeaxtklx7ypyww4q
|
||||
ONTO initial
|
||||
{
|
||||
CREATE TYPE default::Message {
|
||||
CREATE PROPERTY content: std::str;
|
||||
CREATE PROPERTY date: std::datetime;
|
||||
CREATE PROPERTY model_id: std::str;
|
||||
};
|
||||
CREATE TYPE default::Area {
|
||||
CREATE MULTI LINK messages: default::Message;
|
||||
CREATE REQUIRED PROPERTY position: std::int16;
|
||||
};
|
||||
CREATE TYPE default::Conversation {
|
||||
CREATE MULTI LINK areas: default::Area;
|
||||
CREATE REQUIRED PROPERTY name: std::str;
|
||||
};
|
||||
CREATE TYPE default::Key {
|
||||
CREATE PROPERTY date: std::datetime;
|
||||
CREATE PROPERTY key: std::str;
|
||||
CREATE PROPERTY name: std::str;
|
||||
};
|
||||
CREATE TYPE default::Setting {
|
||||
CREATE MULTI LINK keys: default::Key;
|
||||
CREATE PROPERTY default_model: std::str;
|
||||
};
|
||||
CREATE TYPE default::Usage {
|
||||
CREATE PROPERTY date: std::datetime;
|
||||
CREATE PROPERTY input_cost: std::float32;
|
||||
CREATE PROPERTY input_token: std::int32;
|
||||
CREATE PROPERTY model_id: std::str;
|
||||
CREATE PROPERTY output_cost: std::float32;
|
||||
CREATE PROPERTY output_token: std::int32;
|
||||
};
|
||||
CREATE TYPE default::User {
|
||||
CREATE MULTI LINK conversations: default::Conversation;
|
||||
CREATE REQUIRED LINK setting: default::Setting;
|
||||
CREATE MULTI LINK usages: default::Usage;
|
||||
CREATE REQUIRED PROPERTY email: std::str;
|
||||
CREATE REQUIRED PROPERTY name: std::str;
|
||||
};
|
||||
};
|
7
dbschema/migrations/00002-m1jr6zf.edgeql
Normal file
7
dbschema/migrations/00002-m1jr6zf.edgeql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE MIGRATION m1jr6zfrtfdqlhsqlrbtfycstnqth7g62qfo67vhisccw76jsq2wmq
|
||||
ONTO m1oqsdj6bfa6gqquonw63gm53g6zo2uf2cjicsjeaxtklx7ypyww4q
|
||||
{
|
||||
ALTER TYPE default::Message {
|
||||
CREATE PROPERTY role: std::str;
|
||||
};
|
||||
};
|
40
dbschema/migrations/00003-m17at26.edgeql
Normal file
40
dbschema/migrations/00003-m17at26.edgeql
Normal file
@ -0,0 +1,40 @@
|
||||
CREATE MIGRATION m17at265bea5qijan5gj7m7iloworwh6jjjhc76454zus24supt5pa
|
||||
ONTO m1jr6zfrtfdqlhsqlrbtfycstnqth7g62qfo67vhisccw76jsq2wmq
|
||||
{
|
||||
ALTER TYPE default::Key {
|
||||
CREATE REQUIRED PROPERTY company: std::str {
|
||||
SET REQUIRED USING (<std::str>{});
|
||||
};
|
||||
ALTER PROPERTY date {
|
||||
SET REQUIRED USING (<std::datetime>{});
|
||||
};
|
||||
ALTER PROPERTY key {
|
||||
SET REQUIRED USING (<std::str>{});
|
||||
};
|
||||
ALTER PROPERTY name {
|
||||
SET REQUIRED USING (<std::str>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Message {
|
||||
ALTER PROPERTY content {
|
||||
SET REQUIRED USING (<std::str>{});
|
||||
};
|
||||
ALTER PROPERTY date {
|
||||
SET REQUIRED USING (<std::datetime>{});
|
||||
};
|
||||
ALTER PROPERTY model_id {
|
||||
SET REQUIRED USING (<std::str>{});
|
||||
};
|
||||
ALTER PROPERTY role {
|
||||
SET REQUIRED USING (<std::str>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Usage {
|
||||
ALTER PROPERTY date {
|
||||
SET REQUIRED USING (<std::datetime>{});
|
||||
};
|
||||
ALTER PROPERTY model_id {
|
||||
SET REQUIRED USING (<std::str>{});
|
||||
};
|
||||
};
|
||||
};
|
27
dbschema/migrations/00004-m1mrvqa.edgeql
Normal file
27
dbschema/migrations/00004-m1mrvqa.edgeql
Normal file
@ -0,0 +1,27 @@
|
||||
CREATE MIGRATION m1mrvqaliipkuj6qkdsure7odari66nwav3djramxwdws6uezom5ja
|
||||
ONTO m17at265bea5qijan5gj7m7iloworwh6jjjhc76454zus24supt5pa
|
||||
{
|
||||
ALTER TYPE default::Conversation {
|
||||
CREATE PROPERTY date: std::datetime {
|
||||
SET default := (std::datetime_current());
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Key {
|
||||
ALTER PROPERTY date {
|
||||
SET default := (std::datetime_current());
|
||||
RESET OPTIONALITY;
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Message {
|
||||
ALTER PROPERTY date {
|
||||
SET default := (std::datetime_current());
|
||||
RESET OPTIONALITY;
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Usage {
|
||||
ALTER PROPERTY date {
|
||||
SET default := (std::datetime_current());
|
||||
RESET OPTIONALITY;
|
||||
};
|
||||
};
|
||||
};
|
9
dbschema/migrations/00005-m1yui4p.edgeql
Normal file
9
dbschema/migrations/00005-m1yui4p.edgeql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE MIGRATION m1yui4pyoh7ebe7txsda2ctarywhthxaxs3taqavem36job6zqjvua
|
||||
ONTO m1mrvqaliipkuj6qkdsure7odari66nwav3djramxwdws6uezom5ja
|
||||
{
|
||||
ALTER TYPE default::Message {
|
||||
ALTER PROPERTY model_id {
|
||||
RESET OPTIONALITY;
|
||||
};
|
||||
};
|
||||
};
|
7
dbschema/migrations/00006-m14yikr.edgeql
Normal file
7
dbschema/migrations/00006-m14yikr.edgeql
Normal file
@ -0,0 +1,7 @@
|
||||
CREATE MIGRATION m14yikr2253u3hvn6fnj77xjb4uo6o7alftodkyss4koizfpzpzgrq
|
||||
ONTO m1yui4pyoh7ebe7txsda2ctarywhthxaxs3taqavem36job6zqjvua
|
||||
{
|
||||
ALTER TYPE default::Message {
|
||||
CREATE PROPERTY selected: std::bool;
|
||||
};
|
||||
};
|
24
dbschema/migrations/00007-m13hbv6.edgeql
Normal file
24
dbschema/migrations/00007-m13hbv6.edgeql
Normal file
@ -0,0 +1,24 @@
|
||||
CREATE MIGRATION m13hbv6nrii3ccn7hsdboex4rupj7t5wfo3zfx5aki34rqgnflmvva
|
||||
ONTO m14yikr2253u3hvn6fnj77xjb4uo6o7alftodkyss4koizfpzpzgrq
|
||||
{
|
||||
ALTER TYPE default::Conversation {
|
||||
ALTER PROPERTY date {
|
||||
SET REQUIRED USING (<std::datetime>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Key {
|
||||
ALTER PROPERTY date {
|
||||
SET REQUIRED USING (<std::datetime>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Message {
|
||||
ALTER PROPERTY date {
|
||||
SET REQUIRED USING (<std::datetime>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Usage {
|
||||
ALTER PROPERTY date {
|
||||
SET REQUIRED USING (<std::datetime>{});
|
||||
};
|
||||
};
|
||||
};
|
9
dbschema/migrations/00008-m16uely.edgeql
Normal file
9
dbschema/migrations/00008-m16uely.edgeql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE MIGRATION m16uelygvrzoeahpszkv3bknrlklfgoqxhlfxyd5pnup6qpwalmr6q
|
||||
ONTO m13hbv6nrii3ccn7hsdboex4rupj7t5wfo3zfx5aki34rqgnflmvva
|
||||
{
|
||||
ALTER TYPE default::Area {
|
||||
ALTER PROPERTY position {
|
||||
SET TYPE std::int64;
|
||||
};
|
||||
};
|
||||
};
|
47
dbschema/migrations/00009-m1qfy6o.edgeql
Normal file
47
dbschema/migrations/00009-m1qfy6o.edgeql
Normal file
@ -0,0 +1,47 @@
|
||||
CREATE MIGRATION m1qfy6oqj3g3bhjhemjyxr3zdlwi4a3gqi5mgj7kbxfimxxwreezha
|
||||
ONTO m16uelygvrzoeahpszkv3bknrlklfgoqxhlfxyd5pnup6qpwalmr6q
|
||||
{
|
||||
ALTER TYPE default::Area {
|
||||
CREATE REQUIRED LINK conversation: default::Conversation {
|
||||
SET REQUIRED USING (<default::Conversation>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Area {
|
||||
DROP LINK messages;
|
||||
};
|
||||
ALTER TYPE default::Conversation {
|
||||
DROP LINK areas;
|
||||
};
|
||||
ALTER TYPE default::Conversation {
|
||||
CREATE REQUIRED LINK user: default::User {
|
||||
SET REQUIRED USING (<default::User>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Key {
|
||||
CREATE REQUIRED LINK setting: default::Setting {
|
||||
SET REQUIRED USING (<default::Setting>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Message {
|
||||
CREATE REQUIRED LINK area: default::Area {
|
||||
SET REQUIRED USING (<default::Area>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Setting {
|
||||
DROP LINK keys;
|
||||
};
|
||||
ALTER TYPE default::Setting {
|
||||
CREATE REQUIRED LINK user: default::User {
|
||||
SET REQUIRED USING (<default::User>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Usage {
|
||||
CREATE REQUIRED LINK user: default::User {
|
||||
SET REQUIRED USING (<default::User>{});
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::User {
|
||||
DROP LINK conversations;
|
||||
DROP LINK usages;
|
||||
};
|
||||
};
|
13
dbschema/migrations/00010-m1bfwyb.edgeql
Normal file
13
dbschema/migrations/00010-m1bfwyb.edgeql
Normal file
@ -0,0 +1,13 @@
|
||||
CREATE MIGRATION m1bfwybep24ydux23oiyifrk3jstmmnp5y4ronenvefkytuilshgeq
|
||||
ONTO m1qfy6oqj3g3bhjhemjyxr3zdlwi4a3gqi5mgj7kbxfimxxwreezha
|
||||
{
|
||||
ALTER TYPE default::Key {
|
||||
DROP LINK setting;
|
||||
};
|
||||
ALTER TYPE default::Setting {
|
||||
CREATE MULTI LINK keys: default::Key;
|
||||
};
|
||||
ALTER TYPE default::Setting {
|
||||
DROP LINK user;
|
||||
};
|
||||
};
|
9
dbschema/migrations/00011-m1jujti.edgeql
Normal file
9
dbschema/migrations/00011-m1jujti.edgeql
Normal file
@ -0,0 +1,9 @@
|
||||
CREATE MIGRATION m1jujti5v3cgy77tyz42czyxxfntyndf53lxre77nlf4mrwsgrscoq
|
||||
ONTO m1bfwybep24ydux23oiyifrk3jstmmnp5y4ronenvefkytuilshgeq
|
||||
{
|
||||
ALTER TYPE default::Message {
|
||||
CREATE REQUIRED LINK conversation: default::Conversation {
|
||||
SET REQUIRED USING (<default::Conversation>{});
|
||||
};
|
||||
};
|
||||
};
|
19
dbschema/migrations/00012-m16dflw.edgeql
Normal file
19
dbschema/migrations/00012-m16dflw.edgeql
Normal file
@ -0,0 +1,19 @@
|
||||
CREATE MIGRATION m16dflw7c2tzuugatxe7g7ngx6ddn6eczk7a7a6oo5zlixscu565ta
|
||||
ONTO m1jujti5v3cgy77tyz42czyxxfntyndf53lxre77nlf4mrwsgrscoq
|
||||
{
|
||||
ALTER TYPE default::Area {
|
||||
ALTER LINK conversation {
|
||||
ON TARGET DELETE DELETE SOURCE;
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Conversation {
|
||||
ALTER LINK user {
|
||||
ON TARGET DELETE DELETE SOURCE;
|
||||
};
|
||||
};
|
||||
ALTER TYPE default::Message {
|
||||
ALTER LINK area {
|
||||
ON TARGET DELETE DELETE SOURCE;
|
||||
};
|
||||
};
|
||||
};
|
1
edgedb.key
Normal file
1
edgedb.key
Normal file
@ -0,0 +1 @@
|
||||
nbwt1_eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJlZGIuZC5hbGwiOnRydWUsImVkYi5pIjpbIk1yQm91bnR5L0pBREUiXSwiZWRiLnIuYWxsIjp0cnVlLCJpYXQiOjE3MTQ2NzcwMjQsImlzcyI6ImF3cy5lZGdlZGIuY2xvdWQiLCJqdGkiOiJvVUJNaWdpM0VlLXZ5MXZMejdLQUNBIiwic3ViIjoic3BWSkxBTV9FZS0yY1dfZzRSY1V0ZyJ9.awIKoPzGKsBzAfTgI2HwmmFf8fbHKTsVV57M3lFSn2jbPEMEZhtwJdvsRoPGRiD922qSFFVmcPQ_IKkVNVZT6g
|
2
edgedb.toml
Normal file
2
edgedb.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[edgedb]
|
||||
server-version = "5.2"
|
Loading…
x
Reference in New Issue
Block a user