memoryweave/go/internal/api/routes/feedback.go

111 lines
2.9 KiB
Go

// 织忆 MemoryWeave — 反馈 API
package routes
import (
"encoding/json"
"net/http"
"github.com/xiaoxue/memoryweave/internal/selfoptimize"
"github.com/xiaoxue/memoryweave/internal/storage"
)
type FeedbackAPI struct {
LanceDB storage.LanceDB
}
func NewFeedbackAPI(ldb storage.LanceDB) *FeedbackAPI {
return &FeedbackAPI{LanceDB: ldb}
}
// POST /api/v1/feedback/useful
func (fa *FeedbackAPI) MarkUseful(w http.ResponseWriter, r *http.Request) {
var req struct {
MemoryID string `json:"memory_id"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, 400, "invalid body")
return
}
if req.MemoryID == "" {
respondError(w, 400, "memory_id required")
return
}
selfoptimize.Dash.RecordFeedback(true)
fa.LanceDB.IncrementUseful(req.MemoryID)
respond(w, 200, map[string]string{"status": "ok", "memory_id": req.MemoryID})
}
// POST /api/v1/feedback/not-useful
func (fa *FeedbackAPI) MarkNotUseful(w http.ResponseWriter, r *http.Request) {
var req struct {
MemoryID string `json:"memory_id"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, 400, "invalid body")
return
}
if req.MemoryID == "" {
respondError(w, 400, "memory_id required")
return
}
selfoptimize.Dash.RecordFeedback(false)
fa.LanceDB.IncrementNotUseful(req.MemoryID)
respond(w, 200, map[string]string{"status": "ok", "memory_id": req.MemoryID})
}
// POST /api/v1/feedback/deprecate
func (fa *FeedbackAPI) Deprecate(w http.ResponseWriter, r *http.Request) {
var req struct {
MemoryID string `json:"memory_id"`
Reason string `json:"reason"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, 400, "invalid body")
return
}
if req.MemoryID == "" {
respondError(w, 400, "memory_id required")
return
}
selfoptimize.Dash.RecordDeprecation()
fa.LanceDB.SoftDelete(req.MemoryID, req.Reason)
respond(w, 200, map[string]string{"status": "deprecated", "memory_id": req.MemoryID})
}
// POST /api/v1/feedback/correct
func (fa *FeedbackAPI) Correct(w http.ResponseWriter, r *http.Request) {
var req struct {
MemoryID string `json:"memory_id"`
NewContent string `json:"new_content"`
Source string `json:"source"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, 400, "invalid body")
return
}
if req.MemoryID == "" || req.NewContent == "" {
respondError(w, 400, "memory_id and new_content required")
return
}
if req.Source == "" {
req.Source = "muchen_correction"
}
selfoptimize.Dash.RecordCorrection(req.Source)
// 记录 V 值决策:用户修正 = success
selfoptimize.VProp.RecordDecision(
"correct_"+req.MemoryID,
[]string{req.MemoryID},
"user_correct", "success", "",
)
err := fa.LanceDB.UpdateMemoryContent(req.MemoryID, req.NewContent, req.Source)
if err != nil {
respondError(w, 500, "correct failed: "+err.Error())
return
}
respond(w, 200, map[string]string{"status": "corrected", "memory_id": req.MemoryID})
}