Initial commit: my-brain-importer RAG knowledge management agent
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
99
internal/brain/ingest_json.go
Executable file
99
internal/brain/ingest_json.go
Executable file
@@ -0,0 +1,99 @@
|
||||
// ingest_json.go – Importiert KI-Bildbeschreibungen aus einer JSON-Datei in Qdrant
|
||||
package brain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
pb "github.com/qdrant/go-client/qdrant"
|
||||
openai "github.com/sashabaranov/go-openai"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
||||
"my-brain-importer/internal/config"
|
||||
)
|
||||
|
||||
// ImageEntry entspricht der JSON-Ausgabe von analyze-images.go
|
||||
type ImageEntry struct {
|
||||
FilePath string `json:"file_path"`
|
||||
FileName string `json:"file_name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// RunIngestJSON importiert Bildbeschreibungen aus einer JSON-Datei in Qdrant.
|
||||
func RunIngestJSON(inputFile string) {
|
||||
fmt.Printf("📂 Lade \"%s\"...\n", inputFile)
|
||||
raw, err := os.ReadFile(inputFile)
|
||||
if err != nil {
|
||||
log.Fatalf("❌ Datei nicht gefunden: %v", err)
|
||||
}
|
||||
|
||||
var entries []ImageEntry
|
||||
if err := json.Unmarshal(raw, &entries); err != nil {
|
||||
log.Fatalf("❌ JSON Fehler: %v", err)
|
||||
}
|
||||
if len(entries) == 0 {
|
||||
log.Fatal("❌ Keine Einträge in JSON")
|
||||
}
|
||||
fmt.Printf("✅ %d Einträge geladen\n\n", len(entries))
|
||||
|
||||
ctx := context.Background()
|
||||
ctx = metadata.AppendToOutgoingContext(ctx, "api-key", config.Cfg.Qdrant.APIKey)
|
||||
|
||||
conn := config.NewQdrantConn()
|
||||
defer conn.Close()
|
||||
|
||||
ensureCollection(ctx, pb.NewCollectionsClient(conn))
|
||||
pointsClient := pb.NewPointsClient(conn)
|
||||
embClient := config.NewEmbeddingClient()
|
||||
|
||||
fmt.Printf("🤖 Embedding: %s (%s)\n\n", config.Cfg.Embedding.Model, config.Cfg.Embedding.URL)
|
||||
|
||||
success := 0
|
||||
for i, entry := range entries {
|
||||
fmt.Printf("[%d/%d] 🔄 %s\n", i+1, len(entries), entry.FileName)
|
||||
|
||||
embResp, err := embClient.CreateEmbeddings(ctx, openai.EmbeddingRequest{
|
||||
Input: []string{entry.Description},
|
||||
Model: openai.EmbeddingModel(config.Cfg.Embedding.Model),
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf(" ❌ Embedding Fehler: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = pointsClient.Upsert(ctx, &pb.UpsertPoints{
|
||||
CollectionName: config.Cfg.Qdrant.Collection,
|
||||
Points: []*pb.PointStruct{
|
||||
{
|
||||
Id: &pb.PointId{
|
||||
PointIdOptions: &pb.PointId_Uuid{
|
||||
Uuid: generateID(entry.Description, entry.FileName),
|
||||
},
|
||||
},
|
||||
Vectors: &pb.Vectors{
|
||||
VectorsOptions: &pb.Vectors_Vector{
|
||||
Vector: &pb.Vector{Data: embResp.Data[0].Embedding},
|
||||
},
|
||||
},
|
||||
Payload: map[string]*pb.Value{
|
||||
"text": {Kind: &pb.Value_StringValue{StringValue: entry.Description}},
|
||||
"source": {Kind: &pb.Value_StringValue{StringValue: entry.FileName}},
|
||||
"path": {Kind: &pb.Value_StringValue{StringValue: entry.FilePath}},
|
||||
"type": {Kind: &pb.Value_StringValue{StringValue: "image"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf(" ❌ Speichern Fehler: %v\n", err)
|
||||
} else {
|
||||
success++
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("\n✅ Fertig: %d von %d Bildern importiert\n", success, len(entries))
|
||||
fmt.Printf("🌐 Dashboard: http://%s:6333/dashboard\n", config.Cfg.Qdrant.Host)
|
||||
}
|
||||
Reference in New Issue
Block a user