NewFileKB walks root and indexes plain text chunks (by file, split on blank lines).
(name, root string)
| 27 | |
| 28 | // NewFileKB walks root and indexes plain text chunks (by file, split on blank lines). |
| 29 | func NewFileKB(name, root string) (*FileKB, error) { |
| 30 | f := &FileKB{name: name, root: root} |
| 31 | err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error { |
| 32 | if err != nil { |
| 33 | return err |
| 34 | } |
| 35 | if d.IsDir() { |
| 36 | return nil |
| 37 | } |
| 38 | lower := strings.ToLower(path) |
| 39 | if !strings.HasSuffix(lower, ".md") && !strings.HasSuffix(lower, ".txt") { |
| 40 | return nil |
| 41 | } |
| 42 | b, err := os.ReadFile(path) |
| 43 | if err != nil { |
| 44 | return nil |
| 45 | } |
| 46 | text := string(b) |
| 47 | parts := strings.Split(text, "\n\n") |
| 48 | for i, p := range parts { |
| 49 | p = strings.TrimSpace(p) |
| 50 | if p == "" { |
| 51 | continue |
| 52 | } |
| 53 | rel, _ := filepath.Rel(root, path) |
| 54 | src := rel |
| 55 | if len(parts) > 1 { |
| 56 | src = fmt.Sprintf("%s#%d", filepath.ToSlash(rel), i) |
| 57 | } |
| 58 | f.docs = append(f.docs, docChunk{text: p, source: src}) |
| 59 | } |
| 60 | return nil |
| 61 | }) |
| 62 | if err != nil { |
| 63 | return nil, err |
| 64 | } |
| 65 | return f, nil |
| 66 | } |
| 67 | |
| 68 | // Name implements RetrievalAdapter. |
| 69 | func (f *FileKB) Name() string { return f.name } |