mvc
This commit is contained in:
parent
3f2789b4da
commit
5651b89a6b
|
|
@ -1,4 +1,5 @@
|
|||
reasons.bleve
|
||||
visits.bleve/**
|
||||
visits.bleve
|
||||
# JetBrains / IntelliJ / GoLand project files
|
||||
.idea/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Controller struct to hold dependencies
|
||||
// Add more dependencies as needed
|
||||
// e.g. templates, services, etc.
|
||||
type Controller struct {
|
||||
repo ChatRepositoryAPI
|
||||
llm LLMClientAPI
|
||||
visitDB *VisitDB
|
||||
template TemplateExecutor
|
||||
uiDBEditTemplate TemplateExecutor
|
||||
uiAdminChatsTemplate TemplateExecutor
|
||||
}
|
||||
|
||||
// NewController creates a new Controller instance
|
||||
func NewController(repo ChatRepositoryAPI, llm LLMClientAPI, visitDB *VisitDB, template, uiDBEditTemplate, uiAdminChatsTemplate TemplateExecutor) *Controller {
|
||||
return &Controller{
|
||||
repo: repo,
|
||||
llm: llm,
|
||||
visitDB: visitDB,
|
||||
template: template,
|
||||
uiDBEditTemplate: uiDBEditTemplate,
|
||||
uiAdminChatsTemplate: uiAdminChatsTemplate,
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for root UI
|
||||
func (ctrl *Controller) RootUI(c *gin.Context) {
|
||||
c.Status(http.StatusOK)
|
||||
if err := ctrl.template.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui.html template: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for health check
|
||||
func (ctrl *Controller) Health(c *gin.Context) {
|
||||
c.Status(http.StatusOK)
|
||||
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||
}
|
||||
|
||||
// Handler for chat
|
||||
func (ctrl *Controller) HandleChat(c *gin.Context) {
|
||||
// Use your existing chatService logic here
|
||||
// You may want to move NewChatService to a service file for full MVC
|
||||
chatService := NewChatService(ctrl.llm, ctrl.visitDB, ctrl.repo)
|
||||
chatService.HandleChat(c)
|
||||
}
|
||||
|
||||
// Handler for admin UI
|
||||
func (ctrl *Controller) AdminUI(c *gin.Context) {
|
||||
c.Status(http.StatusOK)
|
||||
if err := ctrl.uiDBEditTemplate.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui_dbedit.html template: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for download db.yaml
|
||||
func (ctrl *Controller) DownloadDB(c *gin.Context) {
|
||||
c.File("db.yaml")
|
||||
}
|
||||
|
||||
// Handler for saving knowledgeModel (snapshot)
|
||||
func (ctrl *Controller) SaveKnowledgeModel(c *gin.Context) {
|
||||
if ctrl.repo == nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "repository not configured"})
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
if err := c.BindJSON(&req); err != nil || req.Text == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
|
||||
return
|
||||
}
|
||||
if err := ctrl.repo.SaveKnowledgeModel(c.Request.Context(), req.Text); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save snapshot"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"status": "ok"})
|
||||
}
|
||||
|
||||
// Handler for listing chat interactions
|
||||
func (ctrl *Controller) ListChatInteractions(c *gin.Context) {
|
||||
if ctrl.repo == nil {
|
||||
c.JSON(http.StatusOK, gin.H{"items": []ChatInteraction{}, "pagination": gin.H{"limit": 0, "offset": 0, "count": 0}, "warning": "repository not configured"})
|
||||
return
|
||||
}
|
||||
limit := 50
|
||||
if ls := c.Query("limit"); ls != "" {
|
||||
if v, err := strconv.Atoi(ls); err == nil {
|
||||
limit = v
|
||||
}
|
||||
}
|
||||
offset := 0
|
||||
if osf := c.Query("offset"); osf != "" {
|
||||
if v, err := strconv.Atoi(osf); err == nil {
|
||||
offset = v
|
||||
}
|
||||
}
|
||||
items, err := ctrl.repo.ListChatInteractions(c.Request.Context(), limit, offset)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list interactions"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": items, "pagination": gin.H{"limit": limit, "offset": offset, "count": len(items)}})
|
||||
}
|
||||
|
||||
// Handler for listing LLM events
|
||||
func (ctrl *Controller) ListLLMEvents(c *gin.Context) {
|
||||
corr := c.Query("correlation_id")
|
||||
if corr == "" {
|
||||
if strings.Contains(c.GetHeader("Accept"), "application/json") {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "missing correlation_id"})
|
||||
return
|
||||
}
|
||||
c.Status(http.StatusOK)
|
||||
if err := ctrl.uiAdminChatsTemplate.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui_admin_chats.html template: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if ctrl.repo == nil {
|
||||
c.JSON(http.StatusOK, gin.H{"items": []RawLLMEvent{}, "pagination": gin.H{"limit": 0, "offset": 0, "count": 0}, "warning": "repository not configured"})
|
||||
return
|
||||
}
|
||||
limit := 100
|
||||
if ls := c.Query("limit"); ls != "" {
|
||||
if v, err := strconv.Atoi(ls); err == nil {
|
||||
limit = v
|
||||
}
|
||||
}
|
||||
offset := 0
|
||||
if osf := c.Query("offset"); osf != "" {
|
||||
if v, err := strconv.Atoi(osf); err == nil {
|
||||
offset = v
|
||||
}
|
||||
}
|
||||
events, err := ctrl.repo.ListLLMRawEvents(c.Request.Context(), corr, limit, offset)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list events"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": events, "pagination": gin.H{"limit": limit, "offset": offset, "count": len(events)}})
|
||||
}
|
||||
|
||||
// Handler for admin chats UI
|
||||
func (ctrl *Controller) AdminChatsUI(c *gin.Context) {
|
||||
c.Status(http.StatusOK)
|
||||
if err := ctrl.uiAdminChatsTemplate.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui_admin_chats.html template: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Handler for listing knowledgeModel entries
|
||||
func (ctrl *Controller) ListKnowledgeModels(c *gin.Context) {
|
||||
if ctrl.repo == nil {
|
||||
c.JSON(http.StatusOK, gin.H{"items": []interface{}{}})
|
||||
return
|
||||
}
|
||||
models, err := ctrl.repo.ListKnowledgeModels(c.Request.Context(), 100, 0)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list snapshots"})
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"items": models})
|
||||
}
|
||||
|
||||
// Handler for getting a specific knowledgeModel entry
|
||||
func (ctrl *Controller) GetKnowledgeModel(c *gin.Context) {
|
||||
if ctrl.repo == nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "repository not configured"})
|
||||
return
|
||||
}
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid id"})
|
||||
return
|
||||
}
|
||||
text, err := ctrl.repo.GetKnowledgeModelText(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "snapshot not found"})
|
||||
return
|
||||
}
|
||||
c.Data(http.StatusOK, "text/yaml; charset=utf-8", []byte(text))
|
||||
}
|
||||
|
||||
// TemplateExecutor is an interface for template execution
|
||||
// This allows for easier testing and decoupling
|
||||
// You can implement this interface for your templates
|
||||
|
||||
type TemplateExecutor interface {
|
||||
Execute(wr http.ResponseWriter, data interface{}) error
|
||||
}
|
||||
195
main.go
195
main.go
|
|
@ -2,14 +2,24 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// TemplateWrapper adapts html/template.Template to TemplateExecutor
|
||||
// (implements Execute(http.ResponseWriter, interface{}) error)
|
||||
type TemplateWrapper struct {
|
||||
Tmpl *template.Template
|
||||
}
|
||||
|
||||
func (tw *TemplateWrapper) Execute(wr http.ResponseWriter, data interface{}) error {
|
||||
return tw.Tmpl.Execute(wr, data)
|
||||
}
|
||||
|
||||
func main() {
|
||||
logrus.SetFormatter(&logrus.TextFormatter{FullTimestamp: true})
|
||||
logrus.SetLevel(logrus.InfoLevel)
|
||||
|
|
@ -23,6 +33,12 @@ func main() {
|
|||
if err := loadUITemplate("ui.html"); err != nil {
|
||||
logrus.Fatalf("Failed to load ui.html: %v", err)
|
||||
}
|
||||
if err := loadDBEditTemplate("ui_dbedit.html"); err != nil {
|
||||
logrus.Fatalf("Failed to load ui_dbedit.html: %v", err)
|
||||
}
|
||||
if err := loadAdminChatsTemplate("ui_admin_chats.html"); err != nil {
|
||||
logrus.Fatalf("Failed to load ui_admin_chats.html: %v", err)
|
||||
}
|
||||
|
||||
// Initialize PostgreSQL repository first
|
||||
dsn := buildDefaultDSN()
|
||||
|
|
@ -44,158 +60,39 @@ func main() {
|
|||
)
|
||||
var llm LLMClientAPI = llmClient
|
||||
|
||||
chatService := NewChatService(llm, &visitDB, repo)
|
||||
// Wrap templates for controller
|
||||
uiTmpl := &TemplateWrapper{Tmpl: uiTemplate}
|
||||
uiDBEditTmpl := &TemplateWrapper{Tmpl: uiDBEditTemplate}
|
||||
uiAdminChatsTmpl := &TemplateWrapper{Tmpl: uiAdminChatsTemplate}
|
||||
|
||||
// Create controller
|
||||
ctrl := NewController(
|
||||
repo,
|
||||
llm,
|
||||
&visitDB,
|
||||
uiTmpl,
|
||||
uiDBEditTmpl,
|
||||
uiAdminChatsTmpl,
|
||||
)
|
||||
|
||||
r := gin.Default()
|
||||
// Routes
|
||||
r.GET("/", func(c *gin.Context) {
|
||||
c.Status(200)
|
||||
if err := uiTemplate.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui.html template: %v", err)
|
||||
}
|
||||
})
|
||||
r.GET("/health", func(c *gin.Context) {
|
||||
c.Status(200)
|
||||
c.JSON(200, gin.H{"status": "ok"})
|
||||
})
|
||||
r.POST("/chat", chatService.HandleChat)
|
||||
r.GET("/", ctrl.RootUI)
|
||||
r.GET("/health", ctrl.Health)
|
||||
r.POST("/chat", ctrl.HandleChat)
|
||||
|
||||
if err := loadDBEditTemplate("ui_dbedit.html"); err != nil {
|
||||
logrus.Fatalf("Failed to load ui_dbedit.html: %v", err)
|
||||
}
|
||||
if err := loadAdminChatsTemplate("ui_admin_chats.html"); err != nil {
|
||||
logrus.Fatalf("Failed to load ui_admin_chats.html: %v", err)
|
||||
}
|
||||
r.GET("/admin", func(c *gin.Context) {
|
||||
c.Status(200)
|
||||
if err := uiDBEditTemplate.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui_dbedit.html template: %v", err)
|
||||
}
|
||||
})
|
||||
r.GET("/db.yaml", func(c *gin.Context) { c.File("db.yaml") })
|
||||
r.GET("/admin", ctrl.AdminUI)
|
||||
r.GET("/db.yaml", ctrl.DownloadDB)
|
||||
|
||||
// Add knowledgeModel save endpoint (replaces snapshot)
|
||||
r.POST("/admin/chats/snapshot", func(c *gin.Context) {
|
||||
if repo == nil {
|
||||
c.JSON(500, gin.H{"error": "repository not configured"})
|
||||
return
|
||||
}
|
||||
var req struct {
|
||||
Text string `json:"text"`
|
||||
}
|
||||
if err := c.BindJSON(&req); err != nil || req.Text == "" {
|
||||
c.JSON(400, gin.H{"error": "invalid request"})
|
||||
return
|
||||
}
|
||||
if err := repo.SaveKnowledgeModel(c.Request.Context(), req.Text); err != nil {
|
||||
c.JSON(500, gin.H{"error": "failed to save snapshot"})
|
||||
return
|
||||
}
|
||||
c.JSON(200, gin.H{"status": "ok"})
|
||||
})
|
||||
// KnowledgeModel endpoints (replaces snapshot)
|
||||
r.POST("/admin/chats/snapshot", ctrl.SaveKnowledgeModel)
|
||||
r.GET("/admin/chats/snapshots", ctrl.ListKnowledgeModels)
|
||||
r.GET("/admin/chats/snapshot/:id", ctrl.GetKnowledgeModel)
|
||||
|
||||
// JSON: list chat interactions
|
||||
r.GET("/admin/chats", func(c *gin.Context) {
|
||||
if repo == nil {
|
||||
c.JSON(200, gin.H{"items": []ChatInteraction{}, "pagination": gin.H{"limit": 0, "offset": 0, "count": 0}, "warning": "repository not configured"})
|
||||
return
|
||||
}
|
||||
limit := 50
|
||||
if ls := c.Query("limit"); ls != "" {
|
||||
if v, err := strconv.Atoi(ls); err == nil {
|
||||
limit = v
|
||||
}
|
||||
}
|
||||
offset := 0
|
||||
if osf := c.Query("offset"); osf != "" {
|
||||
if v, err := strconv.Atoi(osf); err == nil {
|
||||
offset = v
|
||||
}
|
||||
}
|
||||
items, err := repo.ListChatInteractions(c.Request.Context(), limit, offset)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": "failed to list interactions"})
|
||||
return
|
||||
}
|
||||
c.JSON(200, gin.H{"items": items, "pagination": gin.H{"limit": limit, "offset": offset, "count": len(items)}})
|
||||
})
|
||||
// JSON: list raw LLM events for a correlation id OR serve UI when no correlation_id provided
|
||||
r.GET("/admin/chats/events", func(c *gin.Context) {
|
||||
corr := c.Query("correlation_id")
|
||||
if corr == "" {
|
||||
if strings.Contains(c.GetHeader("Accept"), "application/json") {
|
||||
c.JSON(400, gin.H{"error": "missing correlation_id"})
|
||||
return
|
||||
}
|
||||
c.Status(200)
|
||||
if err := uiAdminChatsTemplate.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui_admin_chats.html template: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
if repo == nil { // repository not configured, return empty JSON set for events
|
||||
c.JSON(200, gin.H{"items": []RawLLMEvent{}, "pagination": gin.H{"limit": 0, "offset": 0, "count": 0}, "warning": "repository not configured"})
|
||||
return
|
||||
}
|
||||
limit := 100
|
||||
if ls := c.Query("limit"); ls != "" {
|
||||
if v, err := strconv.Atoi(ls); err == nil {
|
||||
limit = v
|
||||
}
|
||||
}
|
||||
offset := 0
|
||||
if osf := c.Query("offset"); osf != "" {
|
||||
if v, err := strconv.Atoi(osf); err == nil {
|
||||
offset = v
|
||||
}
|
||||
}
|
||||
events, err := repo.ListLLMRawEvents(c.Request.Context(), corr, limit, offset)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": "failed to list events"})
|
||||
return
|
||||
}
|
||||
c.JSON(200, gin.H{"items": events, "pagination": gin.H{"limit": limit, "offset": offset, "count": len(events)}})
|
||||
})
|
||||
// HTML UI for chats & events
|
||||
r.GET("/admin/chats/ui", func(c *gin.Context) {
|
||||
c.Status(200)
|
||||
if err := uiAdminChatsTemplate.Execute(c.Writer, nil); err != nil {
|
||||
logrus.Errorf("Failed to execute ui_admin_chats.html template: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
// List knowledgeModel entries (replaces snapshots)
|
||||
r.GET("/admin/chats/snapshots", func(c *gin.Context) {
|
||||
if repo == nil {
|
||||
c.JSON(200, gin.H{"items": []interface{}{}})
|
||||
return
|
||||
}
|
||||
models, err := repo.ListKnowledgeModels(c.Request.Context(), 100, 0)
|
||||
if err != nil {
|
||||
c.JSON(500, gin.H{"error": "failed to list snapshots"})
|
||||
return
|
||||
}
|
||||
c.JSON(200, gin.H{"items": models})
|
||||
})
|
||||
|
||||
// Get a specific knowledgeModel entry (replaces snapshot)
|
||||
r.GET("/admin/chats/snapshot/:id", func(c *gin.Context) {
|
||||
if repo == nil {
|
||||
c.JSON(404, gin.H{"error": "repository not configured"})
|
||||
return
|
||||
}
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseInt(idStr, 10, 64)
|
||||
if err != nil {
|
||||
c.JSON(400, gin.H{"error": "invalid id"})
|
||||
return
|
||||
}
|
||||
text, err := repo.GetKnowledgeModelText(c.Request.Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(404, gin.H{"error": "snapshot not found"})
|
||||
return
|
||||
}
|
||||
c.Data(200, "text/yaml; charset=utf-8", []byte(text))
|
||||
})
|
||||
// Chat interactions and events
|
||||
r.GET("/admin/chats", ctrl.ListChatInteractions)
|
||||
r.GET("/admin/chats/events", ctrl.ListLLMEvents)
|
||||
r.GET("/admin/chats/ui", ctrl.AdminChatsUI)
|
||||
|
||||
r.Run(":8080")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -130,6 +130,10 @@ func (r *PGChatRepository) SaveChatInteraction(ctx context.Context, rec ChatInte
|
|||
if r == nil || r.pool == nil {
|
||||
return nil
|
||||
}
|
||||
// Ensure keywords is not nil to satisfy NOT NULL constraint
|
||||
if rec.Keywords == nil {
|
||||
rec.Keywords = []string{}
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||
defer cancel()
|
||||
_, err := r.pool.Exec(ctx, `INSERT INTO chat_interactions
|
||||
|
|
@ -224,56 +228,62 @@ func (r *PGChatRepository) ListLLMRawEvents(ctx context.Context, correlationID s
|
|||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// SaveKnowledgeModel inserts a new knowledgeModel entry
|
||||
func (r *PGChatRepository) SaveKnowledgeModel(ctx context.Context, text string) error {
|
||||
if r == nil || r.pool == nil {
|
||||
// SaveKnowledgeModel saves a knowledge model snapshot
|
||||
func (p *PGChatRepository) SaveKnowledgeModel(ctx context.Context, text string) error {
|
||||
if p == nil || p.pool == nil {
|
||||
return nil
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
||||
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||
defer cancel()
|
||||
_, err := r.pool.Exec(ctx, `INSERT INTO knowledgeModel (knowledge_text) VALUES ($1)`, text)
|
||||
_, err := p.pool.Exec(ctx, `INSERT INTO knowledgeModel (knowledge_text) VALUES ($1)`, text)
|
||||
if err != nil {
|
||||
logrus.WithError(err).Warn("failed to persist knowledge model")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// ListKnowledgeModels returns a list of knowledgeModel metadata (id, created_at)
|
||||
func (r *PGChatRepository) ListKnowledgeModels(ctx context.Context, limit, offset int) ([]knowledgeModelMeta, error) {
|
||||
if r == nil || r.pool == nil {
|
||||
return nil, nil
|
||||
// ListKnowledgeModels lists knowledge model metadata
|
||||
func (p *PGChatRepository) ListKnowledgeModels(ctx context.Context, limit, offset int) ([]knowledgeModelMeta, error) {
|
||||
if p == nil || p.pool == nil {
|
||||
return []knowledgeModelMeta{}, nil
|
||||
}
|
||||
if limit <= 0 || limit > 1000 {
|
||||
if limit <= 0 || limit > 500 {
|
||||
limit = 100
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
||||
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||
defer cancel()
|
||||
rows, err := r.pool.Query(ctx, `SELECT id, created_at FROM knowledgeModel ORDER BY created_at DESC LIMIT $1 OFFSET $2`, limit, offset)
|
||||
rows, err := p.pool.Query(ctx, `SELECT id, created_at FROM knowledgeModel ORDER BY created_at DESC LIMIT $1 OFFSET $2`, limit, offset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []knowledgeModelMeta
|
||||
for rows.Next() {
|
||||
var s knowledgeModelMeta
|
||||
if err := rows.Scan(&s.ID, &s.CreatedAt); err != nil {
|
||||
var meta knowledgeModelMeta
|
||||
if err := rows.Scan(&meta.ID, &meta.CreatedAt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, s)
|
||||
out = append(out, meta)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// GetKnowledgeModelText returns the knowledge_text for a given id
|
||||
func (r *PGChatRepository) GetKnowledgeModelText(ctx context.Context, id int64) (string, error) {
|
||||
if r == nil || r.pool == nil {
|
||||
// GetKnowledgeModelText retrieves the text of a knowledge model by ID
|
||||
func (p *PGChatRepository) GetKnowledgeModelText(ctx context.Context, id int64) (string, error) {
|
||||
if p == nil || p.pool == nil {
|
||||
return "", nil
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
|
||||
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
|
||||
defer cancel()
|
||||
var text string
|
||||
err := r.pool.QueryRow(ctx, `SELECT knowledge_text FROM knowledgeModel WHERE id=$1`, id).Scan(&text)
|
||||
return text, err
|
||||
err := p.pool.QueryRow(ctx, `SELECT knowledge_text FROM knowledgeModel WHERE id = $1`, id).Scan(&text)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return text, nil
|
||||
}
|
||||
|
||||
// Close releases pool resources
|
||||
|
|
|
|||
Binary file not shown.
Loading…
Reference in New Issue