basic llm request stream
This commit is contained in:
1 parent
f74e4d1043
commit
a92cc76a9a
66 files changed
+1496
-158
No files matched your search
@@ -0,0 +1,182 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"trankilou.fr/lassistanoque/backend/internal/domain"
|
||||
"trankilou.fr/lassistanoque/backend/internal/service/auth"
|
||||
"trankilou.fr/lassistanoque/backend/internal/service/chat"
|
||||
)
|
||||
|
||||
func NewChatGroup(prefix string, e *echo.Group, service *chat.Service, middlewares ...echo.MiddlewareFunc) *echo.Group {
|
||||
chatHandler := &ChatHandler{
|
||||
chatService: service,
|
||||
}
|
||||
auth := e.Group(prefix, middlewares...)
|
||||
|
||||
auth.POST("/:space", chatHandler.NewChat)
|
||||
auth.POST("/:space/:id", chatHandler.NewChatMessage)
|
||||
auth.GET("/:space/all/:page", chatHandler.List)
|
||||
auth.GET("/:space/:id", chatHandler.Get)
|
||||
auth.GET("/:space/:id/subscribe", chatHandler.Subscribe)
|
||||
auth.DELETE("/:space/:id", chatHandler.Delete)
|
||||
return auth
|
||||
}
|
||||
|
||||
type ChatHandler struct {
|
||||
chatService *chat.Service
|
||||
}
|
||||
|
||||
type ChatRequest struct {
|
||||
Prompt string `json:"prompt"`
|
||||
AgentID string `json:"agentID"`
|
||||
ProviderID string `json:"providerID"`
|
||||
ModelID string `json:"modelID"`
|
||||
ReasoningLevel string `json:"reasoningLevel"`
|
||||
}
|
||||
|
||||
func (h *ChatHandler) NewChat(c *echo.Context) error {
|
||||
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||
teamID := c.Param("space")
|
||||
var request ChatRequest
|
||||
err := c.Bind(&request)
|
||||
if err != nil {
|
||||
c.Logger().Error("error binding request", "error", err.Error())
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error binding request")
|
||||
}
|
||||
chat, err := h.chatService.NewChat(
|
||||
userID,
|
||||
teamID,
|
||||
request.AgentID,
|
||||
)
|
||||
if err != nil {
|
||||
c.Logger().Error("error creating chat", "error", err.Error())
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error creating chat")
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, chat)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) NewChatMessage(c *echo.Context) error {
|
||||
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||
teamID := c.Param("space")
|
||||
chatID := c.Param("id")
|
||||
var request ChatRequest
|
||||
err := c.Bind(&request)
|
||||
if err != nil {
|
||||
c.Logger().Error("error binding request", "error", err.Error())
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error binding request")
|
||||
}
|
||||
|
||||
enc := json.NewEncoder(c.Response())
|
||||
chunkChan := make(chan *domain.Chunk)
|
||||
|
||||
_, err = h.chatService.AddChatMessage(
|
||||
c.Request().Context(),
|
||||
userID,
|
||||
teamID,
|
||||
chatID,
|
||||
request.AgentID,
|
||||
request.Prompt,
|
||||
&domain.ChatParams{
|
||||
OnChunk: func(chunk *domain.Chunk) {
|
||||
chunkChan <- chunk
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Logger().Error("error creating chat message", "error", err.Error())
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error creating chat message")
|
||||
}
|
||||
|
||||
enc.Encode(&domain.Chunk{
|
||||
Done: false,
|
||||
Role: string(domain.RoleUser),
|
||||
Content: request.Prompt,
|
||||
})
|
||||
http.NewResponseController(c.Response()).Flush()
|
||||
|
||||
for {
|
||||
chunk := <-chunkChan
|
||||
slog.Info("Chunk", "role", chunk.Role, "content", chunk.Content, "reasoning", chunk.Reasoning)
|
||||
if chunk.Done {
|
||||
return nil
|
||||
}
|
||||
enc.Encode(chunk)
|
||||
http.NewResponseController(c.Response()).Flush()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (h *ChatHandler) List(c *echo.Context) error {
|
||||
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||
teamID := c.Param("space")
|
||||
page := c.Param("page")
|
||||
pageInt, _ := strconv.Atoi(page)
|
||||
chats, err := h.chatService.ListChats(userID, teamID, pageInt)
|
||||
if err != nil {
|
||||
c.Logger().Error("error listing chats", "error", err)
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error listing chats")
|
||||
}
|
||||
return c.JSON(http.StatusOK, chats)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) Get(c *echo.Context) error {
|
||||
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||
teamID := c.Param("space")
|
||||
chatID := c.Param("id")
|
||||
chatWithMessages, err := h.chatService.GetChatWithMessages(userID, teamID, chatID)
|
||||
if err != nil {
|
||||
c.Logger().Error("error getting chat with messages", "error", err)
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error getting chat")
|
||||
}
|
||||
return c.JSON(http.StatusOK, chatWithMessages)
|
||||
}
|
||||
|
||||
func (h *ChatHandler) Delete(c *echo.Context) error {
|
||||
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||
teamID := c.Param("space")
|
||||
chatID := c.Param("id")
|
||||
err := h.chatService.DeleteChat(userID, teamID, chatID)
|
||||
if err != nil {
|
||||
c.Logger().Error("error deleting chat", "error", err)
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error deleting chat")
|
||||
}
|
||||
return c.JSON(http.StatusOK, "chat deleted")
|
||||
}
|
||||
|
||||
func (h *ChatHandler) Subscribe(c *echo.Context) error {
|
||||
userID := c.Get(auth.ContextUserIDKey).(string)
|
||||
teamID := c.Param("space")
|
||||
chatID := c.Param("id")
|
||||
|
||||
enc := json.NewEncoder(c.Response())
|
||||
chunkChan := make(chan *domain.Chunk)
|
||||
|
||||
err := h.chatService.Subscribe(
|
||||
userID,
|
||||
teamID,
|
||||
chatID,
|
||||
func(chunk *domain.Chunk) {
|
||||
chunkChan <- chunk
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
c.Logger().Error("error subscribing to chat", "error", err.Error())
|
||||
return echo.NewHTTPError(http.StatusBadRequest, "error creating chat")
|
||||
}
|
||||
|
||||
for {
|
||||
chunk := <-chunkChan
|
||||
if chunk.Done {
|
||||
return nil
|
||||
}
|
||||
enc.Encode(chunk)
|
||||
http.NewResponseController(c.Response()).Flush()
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user