web-production-saas-starter/go-b2b-starter/src/api/example_cognitive/handler.go
2025-12-16 18:54:41 +04:00

175 lines
5 KiB
Go

package cognitive
import (
"fmt"
"net/http"
"strconv"
"github.com/gin-gonic/gin"
"github.com/moasq/go-b2b-starter/app/example_cognitive/app/services"
"github.com/moasq/go-b2b-starter/app/example_cognitive/domain"
"github.com/moasq/go-b2b-starter/pkg/auth"
"github.com/moasq/go-b2b-starter/pkg/common/errors"
)
type Handler struct {
ragService services.RAGService
embeddingService services.EmbeddingService
}
func NewHandler(ragService services.RAGService, embeddingService services.EmbeddingService) *Handler {
return &Handler{
ragService: ragService,
embeddingService: embeddingService,
}
}
// ChatRequest represents the JSON request body for chat
type ChatRequest struct {
SessionID int32 `json:"session_id,omitempty"`
Message string `json:"message" binding:"required"`
UseRAG bool `json:"use_rag,omitempty"`
MaxDocuments int `json:"max_documents,omitempty"`
ContextHistory int `json:"context_history,omitempty"`
}
// Chat sends a message and gets a response
// @Summary Chat with AI
// @Description Sends a message to the AI and gets a response, optionally using RAG
// @Tags Cognitive
// @Accept json
// @Produce json
// @Param request body ChatRequest true "Chat request"
// @Success 200 {object} github_com_moasq_go-b2b-starter_app_example_cognitive_domain.ChatResponse
// @Failure 400 {object} errors.HTTPError
// @Failure 500 {object} errors.HTTPError
// @Router /example_cognitive/chat [post]
func (h *Handler) Chat(c *gin.Context) {
reqCtx := auth.GetRequestContext(c)
if reqCtx == nil {
c.JSON(http.StatusBadRequest, errors.NewHTTPError(
http.StatusBadRequest,
"missing_context",
"Organization context is required",
))
return
}
var req ChatRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, errors.NewHTTPError(
http.StatusBadRequest,
"invalid_request",
"Invalid JSON format: "+err.Error(),
))
return
}
// Create domain request
chatReq := &domain.ChatRequest{
SessionID: req.SessionID,
Message: req.Message,
UseRAG: req.UseRAG,
MaxDocuments: req.MaxDocuments,
ContextHistory: req.ContextHistory,
}
response, err := h.ragService.Chat(c.Request.Context(), reqCtx.OrganizationID, reqCtx.AccountID, chatReq)
if err != nil {
c.JSON(http.StatusInternalServerError, errors.NewHTTPError(
http.StatusInternalServerError,
"chat_failed",
"Failed to process chat: "+err.Error(),
))
return
}
c.JSON(http.StatusOK, response)
}
// ListSessions lists chat sessions for the current user
// @Summary List chat sessions
// @Description Lists chat sessions for the current user with pagination
// @Tags Cognitive
// @Produce json
// @Param limit query int false "Limit" default(10)
// @Param offset query int false "Offset" default(0)
// @Success 200 {object} map[string]interface{}
// @Failure 500 {object} errors.HTTPError
// @Router /example_cognitive/sessions [get]
func (h *Handler) ListSessions(c *gin.Context) {
reqCtx := auth.GetRequestContext(c)
if reqCtx == nil {
c.JSON(http.StatusBadRequest, errors.NewHTTPError(
http.StatusBadRequest,
"missing_context",
"Organization context is required",
))
return
}
// Parse query parameters
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "10"))
offset, _ := strconv.Atoi(c.DefaultQuery("offset", "0"))
sessions, err := h.ragService.ListSessions(c.Request.Context(), reqCtx.OrganizationID, reqCtx.AccountID, int32(limit), int32(offset))
if err != nil {
c.JSON(http.StatusInternalServerError, errors.NewHTTPError(
http.StatusInternalServerError,
"list_failed",
"Failed to list sessions: "+err.Error(),
))
return
}
c.JSON(http.StatusOK, gin.H{
"sessions": sessions,
"limit": limit,
"offset": offset,
})
}
// GetSessionHistory retrieves messages for a session
// @Summary Get session history
// @Description Retrieves all messages for a chat session
// @Tags Cognitive
// @Produce json
// @Param id path int true "Session ID"
// @Success 200 {array} github_com_moasq_go-b2b-starter_app_example_cognitive_domain.ChatMessage
// @Failure 400 {object} errors.HTTPError
// @Failure 500 {object} errors.HTTPError
// @Router /example_cognitive/sessions/{id}/messages [get]
func (h *Handler) GetSessionHistory(c *gin.Context) {
idParam := c.Param("id")
var sessionID int32
if _, err := fmt.Sscanf(idParam, "%d", &sessionID); err != nil {
c.JSON(http.StatusBadRequest, errors.NewHTTPError(
http.StatusBadRequest,
"invalid_id",
"Session ID must be a valid number",
))
return
}
reqCtx := auth.GetRequestContext(c)
if reqCtx == nil {
c.JSON(http.StatusBadRequest, errors.NewHTTPError(
http.StatusBadRequest,
"missing_context",
"Organization context is required",
))
return
}
messages, err := h.ragService.GetSessionHistory(c.Request.Context(), reqCtx.OrganizationID, sessionID)
if err != nil {
c.JSON(http.StatusInternalServerError, errors.NewHTTPError(
http.StatusInternalServerError,
"fetch_failed",
"Failed to fetch session history: "+err.Error(),
))
return
}
c.JSON(http.StatusOK, messages)
}