175 lines
5 KiB
Go
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)
|
|
}
|