Files
gochat/backend/internal/model/article_embedding.go
T
rogee c72e359e48 Phase 3.1: Help Center semantic search with pgvector
- ArticleEmbeddingRepo (new): Upsert, GetByArticleID, DeleteByArticleID,
  SearchByEmbedding using pgvector cosine distance (vector_embedding column)
- ArticleEmbedding model: add VectorEmbedding pgvector.Vector field
  alongside existing JSONB Embedding (backward compatible)
- ArticleService: add SemanticSearch() — generates query embedding via LLM,
  searches articles by cosine similarity; add GenerateEmbedding() — creates
  and stores article embedding from title+description+content
- ArticleHandler: add SemanticSearch endpoint
  GET /portals/:portal_id/articles/semantic_search?query=...
- bootstrap.go: inject articleEmbeddingRepo + llmProvider into ArticleService
- router.go: register /articles/semantic_search route
- migration 000049: add vector(1536) column to article_embeddings table,
  create ivfflat index, migrate existing JSONB data to vector format

Verified: go build + go vet + go test all pass
2026-07-08 15:38:08 +08:00

21 lines
816 B
Go

package model
import (
"encoding/json"
"github.com/pgvector/pgvector-go"
)
// ArticleEmbedding stores vector embeddings for semantic article search.
// Reference: Chatwoot ArticleEmbedding (enterprise) + P2B M9 spec
type ArticleEmbedding struct {
Base
ArticleID uint `gorm:"not null;index" json:"article_id"`
Embedding json.RawMessage `gorm:"type:jsonb" json:"embedding"` // original JSONB storage (backward compat)
VectorEmbedding pgvector.Vector `gorm:"type:vector(1536)" json:"-"` // pgvector column for cosine similarity search
Term string `gorm:"type:text;not null" json:"term"` // searchable text content
Article Article `gorm:"foreignKey:ArticleID" json:"article,omitempty"`
}
func (ArticleEmbedding) TableName() string { return "article_embeddings" }