refactor
This commit is contained in:
parent
86fe25dbee
commit
e60f0c0ed6
|
|
@ -0,0 +1 @@
|
||||||
|
reasons.bleve
|
||||||
|
|
@ -2,6 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
@ -9,11 +10,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChatService struct {
|
type ChatService struct {
|
||||||
LLM *LLMClient
|
LLM *LLMClient
|
||||||
|
reasonsDB ReasonDB
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewChatService(llm *LLMClient) *ChatService {
|
func NewChatService(llm *LLMClient, db ReasonDB) *ChatService {
|
||||||
return &ChatService{LLM: llm}
|
return &ChatService{LLM: llm, reasonsDB: db}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChatService) HandleChat(c *gin.Context) {
|
func (cs *ChatService) HandleChat(c *gin.Context) {
|
||||||
|
|
@ -22,15 +24,15 @@ func (cs *ChatService) HandleChat(c *gin.Context) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
keywords, err := cs.extractKeywords(ctx, req.Message)
|
keywordsResponse, err := cs.getKeywordsResponse(ctx, req.Message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cs.logChat(req, keywords, nil, "", err)
|
cs.logChat(req, keywordsResponse, nil, "", err)
|
||||||
c.JSON(http.StatusOK, ChatResponse{Match: nil})
|
c.JSON(http.StatusOK, ChatResponse{Match: nil})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
kwArr := cs.keywordsToStrings(keywords["keyword"])
|
keywordList := cs.keywordsToStrings(keywordsResponse["keyword"])
|
||||||
best, bestID, candidates, err := cs.findBestCandidate(ctx, req, kwArr)
|
best, err := cs.findVisitReason(ctx, req, keywordList)
|
||||||
cs.logChat(req, keywords, candidates, bestID, err)
|
|
||||||
resp := cs.buildResponse(best)
|
resp := cs.buildResponse(best)
|
||||||
c.JSON(http.StatusOK, resp)
|
c.JSON(http.StatusOK, resp)
|
||||||
}
|
}
|
||||||
|
|
@ -45,7 +47,7 @@ func (cs *ChatService) parseRequest(c *gin.Context) (ChatRequest, error) {
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChatService) extractKeywords(ctx context.Context, message string) (map[string]interface{}, error) {
|
func (cs *ChatService) getKeywordsResponse(ctx context.Context, message string) (map[string]interface{}, error) {
|
||||||
keywords, err := cs.LLM.ExtractKeywords(ctx, message)
|
keywords, err := cs.LLM.ExtractKeywords(ctx, message)
|
||||||
return keywords, err
|
return keywords, err
|
||||||
}
|
}
|
||||||
|
|
@ -65,38 +67,52 @@ func (cs *ChatService) keywordsToStrings(kwIface interface{}) []string {
|
||||||
return kwArr
|
return kwArr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChatService) findBestCandidate(ctx context.Context, req ChatRequest, kwArr []string) (*Reason, string, []Reason, error) {
|
func (cs *ChatService) findVisitReason(ctx context.Context, req ChatRequest, keywordList []string) (*Reason, error) {
|
||||||
candidates := findCandidates(kwArr)
|
logrus.WithFields(logrus.Fields{
|
||||||
|
"keywords": keywordList,
|
||||||
|
"message": req.Message,
|
||||||
|
}).Info("Finding visit reason candidates")
|
||||||
|
|
||||||
|
candidateReasonse, err := cs.reasonsDB.findCandidates(keywordList)
|
||||||
|
logrus.WithFields(logrus.Fields{
|
||||||
|
"candidates": candidateReasonse,
|
||||||
|
"error": err,
|
||||||
|
}).Info("Candidate reasons found")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
bestID := ""
|
bestID := ""
|
||||||
var err error
|
if len(candidateReasonse) > 0 {
|
||||||
if len(candidates) > 0 {
|
bestID, err = cs.LLM.DisambiguateBestMatch(ctx, req.Message, candidateReasonse)
|
||||||
bestID, err = cs.LLM.DisambiguateBestMatch(ctx, req.Message, candidates)
|
logrus.WithFields(logrus.Fields{
|
||||||
|
"bestID": bestID,
|
||||||
|
"error": err,
|
||||||
|
}).Info("Disambiguated best match")
|
||||||
}
|
}
|
||||||
var best *Reason
|
reason, err := cs.reasonsDB.findById(bestID)
|
||||||
for i := range candidates {
|
if err != nil {
|
||||||
if candidates[i].ID == bestID {
|
return nil, fmt.Errorf("findById: %w", err)
|
||||||
best = &candidates[i]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if err != nil || len(kwArr) == 0 || len(candidates) == 0 || bestID == "" || best == nil {
|
return &reason, nil
|
||||||
return nil, bestID, candidates, err
|
|
||||||
}
|
|
||||||
return best, bestID, candidates, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChatService) buildResponse(best *Reason) ChatResponse {
|
func (cs *ChatService) buildResponse(best *Reason) ChatResponse {
|
||||||
if best == nil {
|
if best == nil {
|
||||||
return ChatResponse{Match: nil}
|
resp := ChatResponse{Match: nil}
|
||||||
|
logrus.WithFields(logrus.Fields{"response": resp}).Info("Build response: no match")
|
||||||
|
return resp
|
||||||
}
|
}
|
||||||
totalPrice, totalDuration := sumProcedures(best.Procedures)
|
totalPrice, totalDuration := sumProcedures(best.Procedures)
|
||||||
return ChatResponse{
|
resp := ChatResponse{
|
||||||
Match: &best.ID,
|
Match: &best.ID,
|
||||||
Procedures: best.Procedures,
|
Procedures: best.Procedures,
|
||||||
TotalPrice: totalPrice,
|
TotalPrice: totalPrice,
|
||||||
TotalDuration: totalDuration,
|
TotalDuration: totalDuration,
|
||||||
Notes: best.Notes,
|
Notes: best.Notes,
|
||||||
}
|
}
|
||||||
|
logrus.WithFields(logrus.Fields{"response": resp}).Info("Build response: match found")
|
||||||
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cs *ChatService) logChat(req ChatRequest, keywords map[string]interface{}, candidates []Reason, bestID string, err error) {
|
func (cs *ChatService) logChat(req ChatRequest, keywords map[string]interface{}, candidates []Reason, bestID string, err error) {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
llm:
|
llm:
|
||||||
extract_keywords_prompt: "Translate [{{.Message}}] to English, then output only 3–5 comma-separated veterinary-related keywords derived strictly from [{{.Message}}]. example output [\"keyword1\",\"keyword2\"] No other text, no extra punctuation, no explanations, no quotes, no formatting."
|
extract_keywords_prompt: "Translate [{{.Message}}] to English, then output only 3–5 comma-separated veterinary-related keywords IN ENGLISH derived strictly from [{{.Message}}]. example output [\"keyword1\",\"keyword2\"] No other text, no extra punctuation, no explanations, no quotes, no formatting."
|
||||||
disambiguate_prompt: "Given these possible vet visit reasons: {{.Entries}}, choose the single best match for this user message: {{.Message}}. Reply with the id or none."
|
disambiguate_prompt: "Given these possible vet visit reasons: [{{.Entries}}], choose the single best match for this user message: {{.Message}}. Reply with id ex {\"visitReason\":\"bloodwork\"} No other text, no extra punctuation, no explanations, no quotes, no formatting."
|
||||||
|
|
||||||
|
|
|
||||||
81
db.go
81
db.go
|
|
@ -1,38 +1,97 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
|
"github.com/blevesearch/bleve/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var reasonsDB []Reason
|
type ReasonDB struct {
|
||||||
|
reasonsDB []Reason
|
||||||
|
reasonsIdx bleve.Index
|
||||||
|
}
|
||||||
|
|
||||||
func loadYAMLDB(path string) error {
|
func NewReasonDB() ReasonDB {
|
||||||
|
db := ReasonDB{}
|
||||||
|
db.init()
|
||||||
|
return db
|
||||||
|
}
|
||||||
|
func (rdb *ReasonDB) findById(reasonId string) (Reason, error) {
|
||||||
|
for _, reason := range rdb.reasonsDB {
|
||||||
|
if reason.ID == reasonId {
|
||||||
|
return reason, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Reason{}, errors.New("reason not found")
|
||||||
|
}
|
||||||
|
func (rdb *ReasonDB) init() {
|
||||||
|
idxPath := "reasons.bleve"
|
||||||
|
if _, err := os.Stat(idxPath); err == nil {
|
||||||
|
rdb.reasonsIdx, err = bleve.Open(idxPath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else if os.IsNotExist(err) {
|
||||||
|
rdb.reasonsIdx, err = bleve.New(idxPath, bleve.NewIndexMapping())
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err := rdb.loadYAMLDB("db.yaml")
|
||||||
|
if err != nil {
|
||||||
|
logrus.Fatalf("Failed to load db.yaml: %v", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rdb *ReasonDB) loadYAMLDB(path string) error {
|
||||||
data, err := ioutil.ReadFile(path)
|
data, err := ioutil.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return yaml.Unmarshal(data, &reasonsDB)
|
if err := yaml.Unmarshal(data, &rdb.reasonsDB); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return rdb.indexReasons(rdb.reasonsDB)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rdb *ReasonDB) indexReasons(reasons []Reason) error {
|
||||||
|
batch := rdb.reasonsIdx.NewBatch()
|
||||||
|
for _, reason := range reasons {
|
||||||
|
if err := batch.Index(reason.ID, reason); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rdb.reasonsIdx.Batch(batch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// findCandidates returns reasons with overlapping keywords
|
// findCandidates returns reasons with overlapping keywords
|
||||||
func findCandidates(keywords []string) []Reason {
|
func (rdb *ReasonDB) findCandidates(keywords []string) ([]Reason, error) {
|
||||||
kwSet := make(map[string]struct{})
|
query := bleve.NewMatchQuery(strings.Join(keywords, " "))
|
||||||
for _, k := range keywords {
|
search := bleve.NewSearchRequest(query)
|
||||||
kwSet[k] = struct{}{}
|
searchResults, err := rdb.reasonsIdx.Search(search)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var candidates []Reason
|
var candidates []Reason
|
||||||
for _, r := range reasonsDB {
|
for _, hit := range searchResults.Hits {
|
||||||
for _, k := range r.Keywords {
|
for _, r := range rdb.reasonsDB {
|
||||||
if _, ok := kwSet[strings.ToLower(k)]; ok {
|
if r.ID == hit.ID {
|
||||||
candidates = append(candidates, r)
|
candidates = append(candidates, r)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return candidates
|
return candidates, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// sumProcedures calculates total price and duration
|
// sumProcedures calculates total price and duration
|
||||||
|
|
|
||||||
20
db.yaml
20
db.yaml
|
|
@ -1,6 +1,6 @@
|
||||||
- id: deworming
|
- id: deworming
|
||||||
reason: "Féregtelenítés kutyának"
|
reason: "Féregtelenítés kutyának"
|
||||||
keywords: ["féreg", "féregtelenítés", "parazita", "bélféreg", "kutya"]
|
keywords: ["worm", "deworming", "parasite", "intestinal worm", "dog"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Alap vérvizsgálat"
|
- name: "Alap vérvizsgálat"
|
||||||
price: 12000
|
price: 12000
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
- id: vaccination
|
- id: vaccination
|
||||||
reason: "Oltás kutyának"
|
reason: "Oltás kutyának"
|
||||||
keywords: ["oltás", "vakcina", "oltani", "kutyabetegség", "veszettség"]
|
keywords: ["vaccination", "vaccine", "to vaccinate", "dog disease", "rabies"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Általános állapotfelmérés"
|
- name: "Általános állapotfelmérés"
|
||||||
price: 6000
|
price: 6000
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
- id: neutering
|
- id: neutering
|
||||||
reason: "Ivartalanítás macskának"
|
reason: "Ivartalanítás macskának"
|
||||||
keywords: ["ivartalanítás", "műtét", "macska", "kandúr", "nőstény"]
|
keywords: ["neutering", "surgery", "cat", "tomcat", "female cat"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Műtéti előzetes vizsgálat"
|
- name: "Műtéti előzetes vizsgálat"
|
||||||
price: 15000
|
price: 15000
|
||||||
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
- id: dental_cleaning
|
- id: dental_cleaning
|
||||||
reason: "Fogkő eltávolítás kutyának"
|
reason: "Fogkő eltávolítás kutyának"
|
||||||
keywords: ["fog", "fogkő", "fogsor", "fogtisztítás", "kutyafog"]
|
keywords: ["tooth", "tartar", "dentition", "tooth cleaning", "dog teeth","plaque"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Altatás előtti vizsgálat"
|
- name: "Altatás előtti vizsgálat"
|
||||||
price: 12000
|
price: 12000
|
||||||
|
|
@ -48,7 +48,7 @@
|
||||||
|
|
||||||
- id: checkup
|
- id: checkup
|
||||||
reason: "Általános állapotfelmérés"
|
reason: "Általános állapotfelmérés"
|
||||||
keywords: ["vizsgálat", "ellenőrzés", "checkup", "állapotfelmérés"]
|
keywords: ["examination", "checkup", "check-up", "general assessment"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Teljes fizikai vizsgálat"
|
- name: "Teljes fizikai vizsgálat"
|
||||||
price: 10000
|
price: 10000
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
|
|
||||||
- id: allergy
|
- id: allergy
|
||||||
reason: "Allergiás tünetek vizsgálata"
|
reason: "Allergiás tünetek vizsgálata"
|
||||||
keywords: ["allergia", "viszketés", "kiütés", "bőrpír", "allergiás"]
|
keywords: ["allergy", "itching", "rash", "redness", "allergic"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Bőr- és vérvizsgálat"
|
- name: "Bőr- és vérvizsgálat"
|
||||||
price: 20000
|
price: 20000
|
||||||
|
|
@ -66,7 +66,7 @@
|
||||||
|
|
||||||
- id: ultrasound
|
- id: ultrasound
|
||||||
reason: "Ultrahangos vizsgálat"
|
reason: "Ultrahangos vizsgálat"
|
||||||
keywords: ["ultrahang", "has", "vizsgálat", "UH"]
|
keywords: ["ultrasound", "abdomen", "examination", "US"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Ultrahang vizsgálat"
|
- name: "Ultrahang vizsgálat"
|
||||||
price: 18000
|
price: 18000
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
|
|
||||||
- id: bloodwork
|
- id: bloodwork
|
||||||
reason: "Laborvizsgálat vérből"
|
reason: "Laborvizsgálat vérből"
|
||||||
keywords: ["vér", "vérvizsgálat", "labor", "teszt"]
|
keywords: ["blood", "blood test", "lab", "test"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Teljes vérkép"
|
- name: "Teljes vérkép"
|
||||||
price: 15000
|
price: 15000
|
||||||
|
|
@ -84,7 +84,7 @@
|
||||||
|
|
||||||
- id: xray
|
- id: xray
|
||||||
reason: "Röntgenfelvétel"
|
reason: "Röntgenfelvétel"
|
||||||
keywords: ["röntgen", "csont", "felvétel", "törés"]
|
keywords: ["x-ray", "bone", "scan", "fracture"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Röntgen vizsgálat"
|
- name: "Röntgen vizsgálat"
|
||||||
price: 16000
|
price: 16000
|
||||||
|
|
@ -93,7 +93,7 @@
|
||||||
|
|
||||||
- id: diarrhea
|
- id: diarrhea
|
||||||
reason: "Hasmenés vizsgálata"
|
reason: "Hasmenés vizsgálata"
|
||||||
keywords: ["hasmenés", "hányás", "gyomor", "bél"]
|
keywords: ["diarrhea", "vomiting", "stomach", "intestine"]
|
||||||
procedures:
|
procedures:
|
||||||
- name: "Állatorvosi konzultáció"
|
- name: "Állatorvosi konzultáció"
|
||||||
price: 8000
|
price: 8000
|
||||||
|
|
|
||||||
24
go.mod
24
go.mod
|
|
@ -3,12 +3,32 @@ module vetrag
|
||||||
go 1.25
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/blevesearch/bleve/v2 v2.5.3
|
||||||
github.com/gin-gonic/gin v1.11.0
|
github.com/gin-gonic/gin v1.11.0
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
|
||||||
|
github.com/bits-and-blooms/bitset v1.22.0 // indirect
|
||||||
|
github.com/blevesearch/bleve_index_api v1.2.8 // indirect
|
||||||
|
github.com/blevesearch/geo v0.2.4 // indirect
|
||||||
|
github.com/blevesearch/go-faiss v1.0.25 // indirect
|
||||||
|
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
|
||||||
|
github.com/blevesearch/gtreap v0.1.1 // indirect
|
||||||
|
github.com/blevesearch/mmap-go v1.0.4 // indirect
|
||||||
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 // indirect
|
||||||
|
github.com/blevesearch/segment v0.9.1 // indirect
|
||||||
|
github.com/blevesearch/snowballstem v0.9.0 // indirect
|
||||||
|
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
|
||||||
|
github.com/blevesearch/vellum v1.1.0 // indirect
|
||||||
|
github.com/blevesearch/zapx/v11 v11.4.2 // indirect
|
||||||
|
github.com/blevesearch/zapx/v12 v12.4.2 // indirect
|
||||||
|
github.com/blevesearch/zapx/v13 v13.4.2 // indirect
|
||||||
|
github.com/blevesearch/zapx/v14 v14.4.2 // indirect
|
||||||
|
github.com/blevesearch/zapx/v15 v15.4.2 // indirect
|
||||||
|
github.com/blevesearch/zapx/v16 v16.2.4 // indirect
|
||||||
github.com/bytedance/sonic v1.14.0 // indirect
|
github.com/bytedance/sonic v1.14.0 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
github.com/bytedance/sonic/loader v0.3.0 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.6 // indirect
|
github.com/cloudwego/base64x v0.1.6 // indirect
|
||||||
|
|
@ -19,17 +39,21 @@ require (
|
||||||
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
github.com/go-playground/validator/v10 v10.27.0 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.2 // indirect
|
||||||
github.com/goccy/go-yaml v1.18.0 // indirect
|
github.com/goccy/go-yaml v1.18.0 // indirect
|
||||||
|
github.com/golang/protobuf v1.5.0 // indirect
|
||||||
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
|
github.com/mschoch/smat v0.2.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||||
github.com/quic-go/qpack v0.5.1 // indirect
|
github.com/quic-go/qpack v0.5.1 // indirect
|
||||||
github.com/quic-go/quic-go v0.54.0 // indirect
|
github.com/quic-go/quic-go v0.54.0 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.3.0 // indirect
|
github.com/ugorji/go/codec v1.3.0 // indirect
|
||||||
|
go.etcd.io/bbolt v1.4.0 // indirect
|
||||||
go.uber.org/mock v0.5.0 // indirect
|
go.uber.org/mock v0.5.0 // indirect
|
||||||
golang.org/x/arch v0.20.0 // indirect
|
golang.org/x/arch v0.20.0 // indirect
|
||||||
golang.org/x/crypto v0.40.0 // indirect
|
golang.org/x/crypto v0.40.0 // indirect
|
||||||
|
|
|
||||||
56
go.sum
56
go.sum
|
|
@ -1,3 +1,44 @@
|
||||||
|
github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg=
|
||||||
|
github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0=
|
||||||
|
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||||
|
github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
|
||||||
|
github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||||
|
github.com/blevesearch/bleve/v2 v2.5.3 h1:9l1xtKaETv64SZc1jc4Sy0N804laSa/LeMbYddq1YEM=
|
||||||
|
github.com/blevesearch/bleve/v2 v2.5.3/go.mod h1:Z/e8aWjiq8HeX+nW8qROSxiE0830yQA071dwR3yoMzw=
|
||||||
|
github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
|
||||||
|
github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
|
||||||
|
github.com/blevesearch/geo v0.2.4 h1:ECIGQhw+QALCZaDcogRTNSJYQXRtC8/m8IKiA706cqk=
|
||||||
|
github.com/blevesearch/geo v0.2.4/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
|
||||||
|
github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
|
||||||
|
github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
|
||||||
|
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
|
||||||
|
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
|
||||||
|
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
|
||||||
|
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
|
||||||
|
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
|
||||||
|
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
|
||||||
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.10 h1:Yqk0XD1mE0fDZAJXTjawJ8If/85JxnLd8v5vG/jWE/s=
|
||||||
|
github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8=
|
||||||
|
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
|
||||||
|
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
|
||||||
|
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
|
||||||
|
github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
|
||||||
|
github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A=
|
||||||
|
github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ=
|
||||||
|
github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
|
||||||
|
github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
|
||||||
|
github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
|
||||||
|
github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
|
||||||
|
github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
|
||||||
|
github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
|
||||||
|
github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
|
||||||
|
github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
|
||||||
|
github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
|
||||||
|
github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
|
||||||
|
github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
|
||||||
|
github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
|
||||||
|
github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
|
||||||
|
github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
|
||||||
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ=
|
||||||
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA=
|
||||||
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
|
||||||
|
|
@ -25,9 +66,16 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||||
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
|
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
|
||||||
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y=
|
||||||
|
|
@ -40,6 +88,8 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OH
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
|
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
||||||
|
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
|
@ -64,6 +114,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA=
|
||||||
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4=
|
||||||
|
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||||
|
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||||
|
|
@ -76,6 +128,7 @@ golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||||
|
|
@ -84,10 +137,13 @@ golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||||
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo=
|
||||||
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw=
|
||||||
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
|
||||||
24
llm.go
24
llm.go
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
@ -61,6 +62,13 @@ func (llm *LLMClient) ExtractKeywords(ctx context.Context, message string) (map[
|
||||||
|
|
||||||
// DisambiguateBestMatch calls LLM to pick best match from candidates
|
// DisambiguateBestMatch calls LLM to pick best match from candidates
|
||||||
func (llm *LLMClient) DisambiguateBestMatch(ctx context.Context, message string, candidates []Reason) (string, error) {
|
func (llm *LLMClient) DisambiguateBestMatch(ctx context.Context, message string, candidates []Reason) (string, error) {
|
||||||
|
format := map[string]interface{}{
|
||||||
|
"type": "object",
|
||||||
|
"properties": map[string]interface{}{
|
||||||
|
"visitReason": map[string]interface{}{"type": "string"},
|
||||||
|
},
|
||||||
|
"required": []string{"visitReason"},
|
||||||
|
}
|
||||||
entries, _ := json.Marshal(candidates)
|
entries, _ := json.Marshal(candidates)
|
||||||
prompt, err := renderPrompt(appConfig.LLM.DisambiguatePrompt, map[string]string{"Entries": string(entries), "Message": message})
|
prompt, err := renderPrompt(appConfig.LLM.DisambiguatePrompt, map[string]string{"Entries": string(entries), "Message": message})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -68,16 +76,22 @@ func (llm *LLMClient) DisambiguateBestMatch(ctx context.Context, message string,
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
logrus.WithField("prompt", prompt).Info("[LLM] DisambiguateBestMatch prompt")
|
logrus.WithField("prompt", prompt).Info("[LLM] DisambiguateBestMatch prompt")
|
||||||
resp, err := llm.openAICompletion(ctx, prompt, nil)
|
resp, err := llm.openAICompletion(ctx, prompt, format)
|
||||||
logrus.WithFields(logrus.Fields{"response": resp, "err": err}).Info("[LLM] DisambiguateBestMatch response")
|
logrus.WithFields(logrus.Fields{"response": resp, "err": err}).Info("[LLM] DisambiguateBestMatch response")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
id := strings.TrimSpace(resp)
|
var parsed map[string]string
|
||||||
if id == "none" || id == "null" {
|
if err := json.Unmarshal([]byte(resp), &parsed); err != nil {
|
||||||
return "", nil
|
return "", fmt.Errorf("failed to unmarshal disambiguation response: %w", err)
|
||||||
}
|
}
|
||||||
return id, nil
|
|
||||||
|
visitReason := strings.TrimSpace(parsed["visitReason"])
|
||||||
|
if visitReason == "" {
|
||||||
|
return "", fmt.Errorf("visitReason not found in response")
|
||||||
|
}
|
||||||
|
|
||||||
|
return visitReason, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// openAICompletion calls Ollama API with prompt and structure, returns structured result
|
// openAICompletion calls Ollama API with prompt and structure, returns structured result
|
||||||
|
|
|
||||||
9
main.go
9
main.go
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
@ -16,10 +15,8 @@ func main() {
|
||||||
logrus.Fatalf("Failed to load config.yaml: %v", err)
|
logrus.Fatalf("Failed to load config.yaml: %v", err)
|
||||||
}
|
}
|
||||||
logrus.Infof("Loaded config: %+v", appConfig)
|
logrus.Infof("Loaded config: %+v", appConfig)
|
||||||
if err := loadYAMLDB("db.yaml"); err != nil {
|
reasonDB := NewReasonDB()
|
||||||
logrus.Fatalf("Failed to load db.yaml: %v", err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Loaded %d reasons from db.yaml\n", len(reasonsDB))
|
|
||||||
if err := loadUITemplate("ui.html"); err != nil {
|
if err := loadUITemplate("ui.html"); err != nil {
|
||||||
logrus.Fatalf("Failed to load ui.html: %v", err)
|
logrus.Fatalf("Failed to load ui.html: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -27,7 +24,7 @@ func main() {
|
||||||
APIKey: os.Getenv("OPENAI_API_KEY"),
|
APIKey: os.Getenv("OPENAI_API_KEY"),
|
||||||
BaseURL: os.Getenv("OPENAI_BASE_URL"),
|
BaseURL: os.Getenv("OPENAI_BASE_URL"),
|
||||||
}
|
}
|
||||||
chatService := NewChatService(llm)
|
chatService := NewChatService(llm, reasonDB)
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.GET("/", func(c *gin.Context) {
|
r.GET("/", func(c *gin.Context) {
|
||||||
c.Status(200)
|
c.Status(200)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue