package intelligence import ( "encoding/json" "flag" "fmt" "os" "path/filepath" "sort" "time" "materialanalyzer/internal/model" "materialanalyzer/internal/output" "materialanalyzer/internal/service" ) func Run(args []string) int { fs := flag.NewFlagSet("material-intelligence", flag.ContinueOnError) assetsDir := fs.String("assets-dir", "MaterialAssets", "material asset library directory") outputRoot := fs.String("output-root", ".", "root directory for v3 deliverables") k := fs.Int("k", 5, "nearest neighbors per material in similarity graph") baselineDir := fs.String("baseline-dir", "", "optional old MaterialAssets directory for regression comparison") includeVectors := fs.Bool("include-vectors", true, "include embedding float values in knowledge.db and Embeddings/embeddings.json") if err := fs.Parse(args); err != nil { return 2 } assets, err := loadAssets(*assetsDir) if err != nil { fmt.Fprintf(os.Stderr, "load assets: %v\n", err) return 1 } if len(assets) == 0 { fmt.Fprintln(os.Stderr, "no material assets found") return 1 } if err := buildAll(assets, *assetsDir, *outputRoot, *baselineDir, *k, *includeVectors); err != nil { fmt.Fprintf(os.Stderr, "build intelligence: %v\n", err) return 1 } fmt.Printf("Material Intelligence v3 built: assets=%d output=%s\n", len(assets), *outputRoot) return 0 } func buildAll(assets []loadedAsset, assetsDir, outputRoot, baselineDir string, k int, includeVectors bool) error { now := time.Now().UTC().Format(time.RFC3339) dirs := map[string]string{ "knowledge": filepath.Join(outputRoot, "KnowledgeBase"), "prompts": filepath.Join(outputRoot, "PromptDataset"), "statistics": filepath.Join(outputRoot, "Statistics"), "embeddings": filepath.Join(outputRoot, "Embeddings"), "fingerprint": filepath.Join(outputRoot, "Fingerprints"), "groundtruth": filepath.Join(outputRoot, "GroundTruth"), "regression": filepath.Join(outputRoot, "Regression"), "benchmarks": filepath.Join(outputRoot, "Benchmarks"), } for _, dir := range dirs { if err := os.MkdirAll(dir, 0o755); err != nil { return err } } fingerprints := map[string]MaterialFingerprint{} groundTruths := make([]GroundTruth, 0, len(assets)) prompts := make([]PromptRecord, 0, len(assets)) knowledge := KnowledgeDB{Version: "3.0", GeneratedAt: now} embeddingExports := make([]KnowledgeEntry, 0, len(assets)) for _, item := range assets { fp := buildFingerprint(item.Asset) gt := buildGroundTruth(item.Asset, fp) prompt := buildPromptRecord(item.Asset, gt) embeddings := item.Embeddings if !includeVectors { embeddings = stripEmbeddingValues(embeddings) } entry := KnowledgeEntry{ SKU: item.Asset.SKU, Brand: item.Asset.Product.Brand, Category: item.Asset.Category, Material: item.Asset.Material, Semantic: item.Asset.Semantic, Fingerprint: fp, Embeddings: embeddings, PreviewImage: filepath.Join(item.AssetDir, "preview.jpg"), AssetDir: item.AssetDir, } fingerprints[item.Asset.SKU] = fp groundTruths = append(groundTruths, gt) prompts = append(prompts, prompt) knowledge.Entries = append(knowledge.Entries, entry) embeddingExports = append(embeddingExports, entry) safeName := output.SafePathName(item.Asset.SKU) if err := writeJSON(filepath.Join(dirs["fingerprint"], safeName+".json"), fp); err != nil { return err } if err := writeJSON(filepath.Join(dirs["groundtruth"], safeName+".json"), gt); err != nil { return err } if err := writeSemanticJSON(item.AssetDir, item.Asset); err != nil { return err } if err := updateAssetManifest(item.AssetDir, item.Asset); err != nil { return err } } if err := writeJSON(filepath.Join(dirs["fingerprint"], "fingerprints.json"), mapValues(fingerprints)); err != nil { return err } if err := writeJSON(filepath.Join(dirs["groundtruth"], "ground_truth.json"), groundTruths); err != nil { return err } if err := writeJSON(filepath.Join(dirs["prompts"], "prompt_dataset.json"), prompts); err != nil { return err } if err := writeJSON(filepath.Join(dirs["knowledge"], "knowledge.db"), knowledge); err != nil { return err } similarity := buildSimilarityGraph(assets, fingerprints, k) if err := writeJSON(filepath.Join(dirs["knowledge"], "similarity.json"), similarity); err != nil { return err } if err := writeJSON(filepath.Join(dirs["embeddings"], "embeddings.json"), embeddingExports); err != nil { return err } stats := buildStatistics(assets, fingerprints) if err := writeJSON(filepath.Join(dirs["statistics"], "statistics.json"), stats); err != nil { return err } regression := buildRegressionReport(assets, baselineDir) if err := writeJSON(filepath.Join(dirs["regression"], "regression_report.json"), regression); err != nil { return err } visionBench := buildVisionBenchmark(assets) if err := writeJSON(filepath.Join(dirs["benchmarks"], "benchmark_vision.json"), visionBench); err != nil { return err } summary := BuildSummary{ Assets: len(assets), OutputRoot: outputRoot, KnowledgeDB: filepath.Join(dirs["knowledge"], "knowledge.db"), PromptDataset: filepath.Join(dirs["prompts"], "prompt_dataset.json"), Statistics: filepath.Join(dirs["statistics"], "statistics.json"), } return writeJSON(filepath.Join(outputRoot, "material_intelligence_summary.json"), summary) } func writeSemanticJSON(assetDir string, asset model.MaterialAsset) error { payload := map[string]interface{}{ "sku": asset.SKU, "strategy": "single_provider_passthrough", "fusion": "not_applicable", "final_semantic": asset.Semantic, "providers": []map[string]interface{}{ {"provider": asset.Semantic.Provider, "model": asset.Semantic.Model, "confidence": asset.Semantic.Confidence}, }, } return writeJSON(filepath.Join(assetDir, "semantic.json"), payload) } func updateAssetManifest(assetDir string, asset model.MaterialAsset) error { files := []string{"preview.jpg", "thumbnail.jpg", "material.json", "histogram.json", "embedding.bin", "semantic.json", "manifest.json"} return output.WriteManifest(assetDir, model.AssetManifest{ SKU: asset.SKU, AnalyzerVersion: firstNonEmpty(asset.AnalyzerVersion, service.AnalyzerVersion), FeatureSchema: firstNonEmpty(asset.FeatureSchema, service.FeatureSchema), GeneratedAt: time.Now().UTC().Format(time.RFC3339), Files: files, Status: "complete", Validation: asset.Validation, Warnings: asset.Warnings, }) } func stripEmbeddingValues(records []EmbeddingRecord) []EmbeddingRecord { out := make([]EmbeddingRecord, len(records)) for i, record := range records { record.Values = nil out[i] = record } return out } func mapValues(values map[string]MaterialFingerprint) []MaterialFingerprint { out := make([]MaterialFingerprint, 0, len(values)) for _, value := range values { out = append(out, value) } sort.Slice(out, func(i, j int) bool { return out[i].SKU < out[j].SKU }) return out } func writeJSON(path string, v interface{}) error { file, err := os.Create(path) if err != nil { return err } defer file.Close() enc := json.NewEncoder(file) enc.SetIndent("", " ") enc.SetEscapeHTML(false) return enc.Encode(v) }