refactor: remove dead code from embedding/virtfs/skills (-108 lines)
embedding/embedding.go: - Remove EmbedBatch() (never called in production, test updated to use Embed) - Remove padID field (written but never read) embedding/index.go: - Remove Index.mu mutex (Index is immutable after construction) skills/skills.go: - Remove Index.All() (never called) - Remove Index.Reload() (never called) virtfs/decl.go: - Remove RemoveNode() NodeOption (never used) - Remove RenameNode() NodeOption (never used) - Remove Alias() NodeOption (aliases set directly on struct) virtfs/tree.go: - Remove Tree.Data field (never used) - Remove Tree.Mount() (never called in production) - Remove Tree.Child() (never called in production) - Remove Tree.Children() (never called in production) - Replace indexOf() with strings.IndexByte Tests updated to directly manipulate internal children map where needed.
This commit is contained in:
parent
2b59409845
commit
4a037c0bbe
|
|
@ -128,18 +128,8 @@ func (m *Model) Embed(text string) (Vector, error) {
|
||||||
return meanPool(output, attentionMask, int(seqLen), 384), nil
|
return meanPool(output, attentionMask, int(seqLen), 384), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EmbedBatch embeds multiple texts efficiently.
|
// EmbedBatch is reserved for future batch optimization.
|
||||||
func (m *Model) EmbedBatch(texts []string) ([]Vector, error) {
|
// Currently calls Embed sequentially.
|
||||||
results := make([]Vector, len(texts))
|
|
||||||
for i, text := range texts {
|
|
||||||
vec, err := m.Embed(text)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("embed text %d: %w", i, err)
|
|
||||||
}
|
|
||||||
results[i] = vec
|
|
||||||
}
|
|
||||||
return results, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CosineSimilarity computes the cosine similarity between two vectors.
|
// CosineSimilarity computes the cosine similarity between two vectors.
|
||||||
func CosineSimilarity(a, b Vector) float32 {
|
func CosineSimilarity(a, b Vector) float32 {
|
||||||
|
|
@ -206,7 +196,6 @@ type Tokenizer struct {
|
||||||
maxLen int
|
maxLen int
|
||||||
clsID int
|
clsID int
|
||||||
sepID int
|
sepID int
|
||||||
padID int
|
|
||||||
unkID int
|
unkID int
|
||||||
lowercase bool
|
lowercase bool
|
||||||
}
|
}
|
||||||
|
|
@ -244,7 +233,6 @@ func loadTokenizer(path string) (*Tokenizer, error) {
|
||||||
unkID: 100, // [UNK]
|
unkID: 100, // [UNK]
|
||||||
clsID: 101, // [CLS]
|
clsID: 101, // [CLS]
|
||||||
sepID: 102, // [SEP]
|
sepID: 102, // [SEP]
|
||||||
padID: 0, // [PAD]
|
|
||||||
}
|
}
|
||||||
if tj.Truncation != nil {
|
if tj.Truncation != nil {
|
||||||
tok.maxLen = tj.Truncation.MaxLength
|
tok.maxLen = tj.Truncation.MaxLength
|
||||||
|
|
@ -256,8 +244,6 @@ func loadTokenizer(path string) (*Tokenizer, error) {
|
||||||
// Override IDs from added_tokens if present
|
// Override IDs from added_tokens if present
|
||||||
for _, at := range tj.AddedTokens {
|
for _, at := range tj.AddedTokens {
|
||||||
switch at.Content {
|
switch at.Content {
|
||||||
case "[PAD]":
|
|
||||||
tok.padID = at.ID
|
|
||||||
case "[UNK]":
|
case "[UNK]":
|
||||||
tok.unkID = at.ID
|
tok.unkID = at.ID
|
||||||
case "[CLS]":
|
case "[CLS]":
|
||||||
|
|
|
||||||
|
|
@ -94,9 +94,13 @@ func TestSkillMatching(t *testing.T) {
|
||||||
"Write ast-grep rules for AST-based structural code search and analysis.",
|
"Write ast-grep rules for AST-based structural code search and analysis.",
|
||||||
}
|
}
|
||||||
|
|
||||||
skillVecs, err := model.EmbedBatch(skills)
|
skillVecs := make([]Vector, len(skills))
|
||||||
|
for i, s := range skills {
|
||||||
|
vec, err := model.Embed(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("EmbedBatch: %v", err)
|
t.Fatalf("Embed skill %d: %v", i, err)
|
||||||
|
}
|
||||||
|
skillVecs[i] = vec
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test queries
|
// Test queries
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ package embedding
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Item represents something that can be embedded and matched.
|
// Item represents something that can be embedded and matched.
|
||||||
|
|
@ -13,11 +12,11 @@ type Item struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index holds precomputed embeddings for semantic matching.
|
// Index holds precomputed embeddings for semantic matching.
|
||||||
|
// Index is immutable after construction — no synchronization needed.
|
||||||
type Index struct {
|
type Index struct {
|
||||||
model *Model
|
model *Model
|
||||||
items []Item
|
items []Item
|
||||||
vecs []Vector
|
vecs []Vector
|
||||||
mu sync.RWMutex
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewIndex creates an index from items using the given embedding model.
|
// NewIndex creates an index from items using the given embedding model.
|
||||||
|
|
@ -47,9 +46,6 @@ func NewIndex(model *Model, items []Item) (*Index, error) {
|
||||||
// threshold is the minimum cosine similarity (0-1) to include.
|
// threshold is the minimum cosine similarity (0-1) to include.
|
||||||
// limit is the maximum number of results (0 for no limit).
|
// limit is the maximum number of results (0 for no limit).
|
||||||
func (idx *Index) Match(query string, threshold float32, limit int) ([]MatchResult, error) {
|
func (idx *Index) Match(query string, threshold float32, limit int) ([]MatchResult, error) {
|
||||||
idx.mu.RLock()
|
|
||||||
defer idx.mu.RUnlock()
|
|
||||||
|
|
||||||
if len(idx.items) == 0 {
|
if len(idx.items) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -92,20 +92,6 @@ func (idx *Index) Match(query string, threshold float32, limit int) ([]MatchResu
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// All returns all indexed skills.
|
|
||||||
func (idx *Index) All() []Skill {
|
|
||||||
idx.mu.RLock()
|
|
||||||
defer idx.mu.RUnlock()
|
|
||||||
return append([]Skill(nil), idx.skills...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reload rescans skill directories and updates embeddings.
|
|
||||||
func (idx *Index) Reload(skillDirs []string) error {
|
|
||||||
idx.mu.Lock()
|
|
||||||
defer idx.mu.Unlock()
|
|
||||||
return idx.loadSkillsLocked(skillDirs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (idx *Index) loadSkills(dirs []string) error {
|
func (idx *Index) loadSkills(dirs []string) error {
|
||||||
idx.mu.Lock()
|
idx.mu.Lock()
|
||||||
defer idx.mu.Unlock()
|
defer idx.mu.Unlock()
|
||||||
|
|
|
||||||
|
|
@ -193,21 +193,6 @@ func Rdwr(fn func(context.Context, []byte) ([]byte, error)) NodeOption {
|
||||||
return func(d *FsNodeDecl) { d.Rdwr = fn }
|
return func(d *FsNodeDecl) { d.Rdwr = fn }
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoveNode sets the removal handler for a node.
|
|
||||||
func RemoveNode(fn func() error) NodeOption {
|
|
||||||
return func(d *FsNodeDecl) { d.Remove = fn }
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenameNode sets the rename handler for a node.
|
|
||||||
func RenameNode(fn func(string) error) NodeOption {
|
|
||||||
return func(d *FsNodeDecl) { d.Rename = fn }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Alias adds alternate lookup names for this node.
|
|
||||||
func Alias(names ...string) NodeOption {
|
|
||||||
return func(d *FsNodeDecl) { d.Aliases = append(d.Aliases, names...) }
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatOverride sets a custom stat handler.
|
// StatOverride sets a custom stat handler.
|
||||||
func StatOverride(fn func() os.FileInfo) NodeOption {
|
func StatOverride(fn func() os.FileInfo) NodeOption {
|
||||||
return func(d *FsNodeDecl) { d.Stat = fn }
|
return func(d *FsNodeDecl) { d.Stat = fn }
|
||||||
|
|
|
||||||
|
|
@ -40,16 +40,6 @@ func TestNodeOptions(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("RemoveNode", func(t *testing.T) {
|
|
||||||
spec := DirNode("test",
|
|
||||||
FileNode("child", 0444),
|
|
||||||
RemoveNode(func() error { return nil }),
|
|
||||||
)
|
|
||||||
if spec.Remove == nil {
|
|
||||||
t.Error("Remove not set")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("StatOverride", func(t *testing.T) {
|
t.Run("StatOverride", func(t *testing.T) {
|
||||||
spec := FileNode("test", 0444, StatOverride(func() os.FileInfo {
|
spec := FileNode("test", 0444, StatOverride(func() os.FileInfo {
|
||||||
return &SyntheticFileInfo{Name_: "test"}
|
return &SyntheticFileInfo{Name_: "test"}
|
||||||
|
|
@ -85,35 +75,10 @@ func TestNodeOptions(t *testing.T) {
|
||||||
// Tree tests
|
// Tree tests
|
||||||
// ══════════════════════════════════════════════════════════════════
|
// ══════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
func TestTreeMount(t *testing.T) {
|
|
||||||
parent := &Tree{perm: 0755}
|
|
||||||
child := &Tree{perm: 0755}
|
|
||||||
child.listFn = func(_ []string) ([]os.DirEntry, error) {
|
|
||||||
return []os.DirEntry{fileEntry("childfile", 0444)}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
parent.Mount("subdir", child)
|
|
||||||
|
|
||||||
got := parent.Child("subdir")
|
|
||||||
if got != child {
|
|
||||||
t.Error("Child did not return mounted child")
|
|
||||||
}
|
|
||||||
|
|
||||||
children := parent.Children()
|
|
||||||
if len(children) != 1 {
|
|
||||||
t.Errorf("Children = %d, want 1", len(children))
|
|
||||||
}
|
|
||||||
|
|
||||||
nilChild := parent.Child("nonexistent")
|
|
||||||
if nilChild != nil {
|
|
||||||
t.Error("Child should return nil for nonexistent")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTreeSplit(t *testing.T) {
|
func TestTreeSplit(t *testing.T) {
|
||||||
parent := &Tree{perm: 0755}
|
parent := &Tree{perm: 0755, children: make(map[string]*Tree)}
|
||||||
child := &Tree{perm: 0755}
|
child := &Tree{perm: 0755}
|
||||||
parent.Mount("sub", child)
|
parent.children["sub"] = child
|
||||||
|
|
||||||
c, rest, ok := parent.split("sub")
|
c, rest, ok := parent.split("sub")
|
||||||
if !ok || c != child || rest != "" {
|
if !ok || c != child || rest != "" {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Tree is a synthetic filesystem node.
|
// Tree is a synthetic filesystem node.
|
||||||
|
|
@ -30,28 +31,6 @@ type Tree struct {
|
||||||
statFn func([]string, string) (os.FileInfo, error)
|
statFn func([]string, string) (os.FileInfo, error)
|
||||||
readdirFn func([]string, string) ([]os.DirEntry, error)
|
readdirFn func([]string, string) ([]os.DirEntry, error)
|
||||||
children map[string]*Tree
|
children map[string]*Tree
|
||||||
Data any // user-attached state
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mount attaches a child Tree at the given name.
|
|
||||||
func (d *Tree) Mount(name string, child *Tree) {
|
|
||||||
if d.children == nil {
|
|
||||||
d.children = make(map[string]*Tree)
|
|
||||||
}
|
|
||||||
d.children[name] = child
|
|
||||||
}
|
|
||||||
|
|
||||||
// Child returns the child mounted at name, or nil.
|
|
||||||
func (d *Tree) Child(name string) *Tree {
|
|
||||||
if d.children == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return d.children[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Children returns all mounted children.
|
|
||||||
func (d *Tree) Children() map[string]*Tree {
|
|
||||||
return d.children
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// split checks if name routes to a child tree.
|
// split checks if name routes to a child tree.
|
||||||
|
|
@ -62,7 +41,7 @@ func (d *Tree) split(name string) (*Tree, string, bool) {
|
||||||
if child, ok := d.children[name]; ok {
|
if child, ok := d.children[name]; ok {
|
||||||
return child, "", true
|
return child, "", true
|
||||||
}
|
}
|
||||||
if i := indexOf(name, '/'); i >= 0 {
|
if i := strings.IndexByte(name, '/'); i >= 0 {
|
||||||
prefix := name[:i]
|
prefix := name[:i]
|
||||||
if child, ok := d.children[prefix]; ok {
|
if child, ok := d.children[prefix]; ok {
|
||||||
return child, name[i+1:], true
|
return child, name[i+1:], true
|
||||||
|
|
@ -71,15 +50,6 @@ func (d *Tree) split(name string) (*Tree, string, bool) {
|
||||||
return nil, "", false
|
return nil, "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
func indexOf(s string, b byte) int {
|
|
||||||
for i := range len(s) {
|
|
||||||
if s[i] == b {
|
|
||||||
return i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Tree) Stat(name string) (os.FileInfo, error) {
|
func (d *Tree) Stat(name string) (os.FileInfo, error) {
|
||||||
if child, rest, ok := d.split(name); ok {
|
if child, rest, ok := d.split(name); ok {
|
||||||
if rest == "" {
|
if rest == "" {
|
||||||
|
|
|
||||||
|
|
@ -139,8 +139,8 @@ func TestTreeChildDelegation(t *testing.T) {
|
||||||
return []os.DirEntry{fileEntry("inner", 0644)}, nil
|
return []os.DirEntry{fileEntry("inner", 0644)}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
parent := &Tree{perm: 0755}
|
parent := &Tree{perm: 0755, children: make(map[string]*Tree)}
|
||||||
parent.Mount("sub", child)
|
parent.children["sub"] = child
|
||||||
|
|
||||||
// Open delegated to child
|
// Open delegated to child
|
||||||
f, err := parent.Open("sub/inner")
|
f, err := parent.Open("sub/inner")
|
||||||
|
|
@ -180,8 +180,8 @@ func TestTreeChildDelegation(t *testing.T) {
|
||||||
func TestTreeChildMkdirAll(t *testing.T) {
|
func TestTreeChildMkdirAll(t *testing.T) {
|
||||||
tmpDir := t.TempDir()
|
tmpDir := t.TempDir()
|
||||||
child := &Tree{Tree: []string{tmpDir}, perm: 0755}
|
child := &Tree{Tree: []string{tmpDir}, perm: 0755}
|
||||||
parent := &Tree{perm: 0755}
|
parent := &Tree{perm: 0755, children: make(map[string]*Tree)}
|
||||||
parent.Mount("sub", child)
|
parent.children["sub"] = child
|
||||||
|
|
||||||
err := parent.MkdirAll("sub/new/deep/path")
|
err := parent.MkdirAll("sub/new/deep/path")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue