feat(rag): pgvector knowledge base with API and LLM tools
Cyrene CI / backend (push) Has been cancelled
Cyrene CI / frontend (push) Has been cancelled

- services/rag: knowledge_docs store — vector search via the shared
  embedder (HNSW index, graceful ILIKE fallback), list/delete scoped to
  the user, search intentionally global for the single-user deployment
- gateway: GET/POST /knowledge/docs, DELETE /knowledge/docs/:id,
  POST /knowledge/search
- plugins/knowledge: knowledge_search and knowledge_ingest tools so the
  persona can save and recall information mid-conversation
- main: migrations, store wiring, plugin registration
This commit is contained in:
Aska committed 2026-08-21 18:40:01 +08:00
1 parent ac0c2b2c73
commit 9c8d5a9e8d
6 files changed
+432 -2

No files matched your search

+19
View File
@@ -32,6 +32,7 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/plugins/text"
webfetch "git.yeij.top/AskaEth/Cyrene_v2/plugins/web-fetch"
websearch "git.yeij.top/AskaEth/Cyrene_v2/plugins/web-search"
"git.yeij.top/AskaEth/Cyrene_v2/plugins/knowledge"
"git.yeij.top/AskaEth/Cyrene_v2/services/ai-core/background"
"git.yeij.top/AskaEth/Cyrene_v2/services/ai-core/emotion"
@@ -49,6 +50,7 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/services/gateway/store"
"git.yeij.top/AskaEth/Cyrene_v2/services/gateway/ws"
"git.yeij.top/AskaEth/Cyrene_v2/services/memory"
"git.yeij.top/AskaEth/Cyrene_v2/services/rag"
bridge "git.yeij.top/AskaEth/Cyrene_v2/services/platform-bridge"
bridgeqq "git.yeij.top/AskaEth/Cyrene_v2/services/platform-bridge/qq"
bridgetg "git.yeij.top/AskaEth/Cyrene_v2/services/platform-bridge/telegram"
@@ -146,6 +148,7 @@ func main() {
// === 6. Memory Service ===
var memSvc *memory.Service
var ragStore *rag.Store
if database != nil {
memRepo := memory.NewRepository(database)
memSvc = memory.NewService(memRepo)
@@ -160,6 +163,19 @@ func main() {
logger.Infof("[memory] hybrid search enabled (vector dims=%d, api=%v)", emb.Dims(), emb.IsAvailable())
}
logger.Infof("[memory] connected")
// === 6.5 Knowledge base (RAG) ===
db.RunMigration(context.Background(), database, "knowledge", db.SplitSQL(rag.CreateTableSQL()))
ragStore = rag.NewStore(database, emb)
if err := db.RunMigration(context.Background(), database, "knowledge-vector", db.SplitSQL(rag.VectorMigrationSQL(emb.Dims()))); err != nil {
logger.Infof("[rag] pgvector unavailable, ILIKE-only search: %v", err)
} else {
ragStore.EnableVector()
}
if err := reg.Register(knowledge.New(ragStore), pluginCfg); err != nil {
logger.Infof("[plugin] knowledge: %v", err)
}
logger.Infof("[rag] knowledge base ready")
} else {
logger.Infof("[memory] disabled (no database)")
}
@@ -316,6 +332,9 @@ func main() {
}
gwDeps.VoiceSvc = voiceSvc
gwDeps.Vision = visionAdapter{llmSelector.DefaultAdapter()}
if ragStore != nil {
gwDeps.Knowledge = ragStore
}
wsHub := ws.NewHub(orch)
gwDeps.WSHub = wsHub