FluxFeed 0.8.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package FluxFeed --version 0.8.0
                    
NuGet\Install-Package FluxFeed -Version 0.8.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FluxFeed" Version="0.8.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FluxFeed" Version="0.8.0" />
                    
Directory.Packages.props
<PackageReference Include="FluxFeed" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FluxFeed --version 0.8.0
                    
#r "nuget: FluxFeed, 0.8.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FluxFeed@0.8.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FluxFeed&version=0.8.0
                    
Install as a Cake Addin
#tool nuget:?package=FluxFeed&version=0.8.0
                    
Install as a Cake Tool

FluxFeed

문서 파이프라인 표면(④b) — 수집·파싱·정제를 묶어 FluxIndex(④a)에 적재(feed)한다. FluxIndex에 비대칭 의존(④b는 ④a 필요, ④a는 ④b 불필요).

Quick Start

// 파일-소스 vault: FileFlux 추출/청킹 + FluxIndex 적재
services.AddFileVaultFactoryWithFluxIndex(o => o.VaultBasePath = "./data");

File selection patterns

FileVaultOptions.DefaultIncludePatterns / DefaultExcludePatternsdiscovery 경로에만 실효한다:

경로 패턴 적용
ScanFolderAsync / SyncAsync ✅ 패턴 밖 파일은 감지·큐잉 전에 skip
폴더 워처 이벤트 ✅ (폴더별 패턴이 기본값보다 우선)
명시적 MemorizeAsync / RefreshAsync ❌ 의도적 미적용 — 명시 호출은 명시 의도이며, 조용히 skip하면 호출자 오류가 숨는다

exclude가 include보다 우선하며, include가 빈 리스트면 "전부 포함"이다.

Extraction diagnostics

추출기가 보고한 구조화 진단은 VaultEntry에 그대로 실려 meta.json에 영속된다. 스캔 PDF처럼 정당한 0청크가 "조용한 성공"으로 보이지 않게 하는 것이 목적이다.

var entry = await vault.MemorizeAsync(path, waitForCompletion: true);  // Stage=Memorized, ChunkCount=0

if (entry.ExtractionHints?.TryGetValue("extraction_failure_reason", out var reason) == true)
{
    // reason: "no_text_layer" (이미지-only/스캔 문서) | "blank_page" (빈 문서)
    // entry.ExtractionWarnings: 사람이 읽는 설명 (예: "... requires OCR")
}
  • 불투명 패스스루 — 키/값은 추출기(FileFlux RawContent.Hints/Warnings) 어휘 그대로다. FluxFeed는 해석하지 않는다.
  • 스칼라만 영속 — 값이 문자열·불리언·수치·날짜류인 힌트만 저장한다. 리더 내부 구조값(예: PageRanges)은 타입명으로 문자열화되어 meta.json을 오염시키므로 제외한다. 키가 아니라 값 타입 기준이라 FileFlux가 힌트를 추가해도 드리프트가 없다.
  • 항상 최신 추출분 — 재추출 시 교체되고, 진단 없이 추출되면 이전 값은 지워진다. 예외 경로 전용인 LastError와는 별개 채널이다.
  • FileFlux 0.14.0+ 필요 (no_text_layer/blank_page 세분 라벨의 출처).

Failure diagnostics

실패 사유는 두 필드로 나뉜다. LastError는 마지막 실패, FirstError는 그 실패 에피소드를 시작한 실패다.

if (entry.FirstError is not null)
{
    // FirstError: 최초 원인 (추출기 분류가 실려 있는 쪽)
    // LastError:  가장 최근 실패 — 재시도가 다른 이유로 실패했다면 다르다
}
  • 재시도가 자기 이유로 실패하면 LastError는 덮이지만 FirstError는 남는다. 최초 실패가 추출기의 진단을 싣고 있으므로, 그것이 지워지면 원본 파일 없이 진단할 방법이 사라진다.
  • FirstErrorLastError같은 생애를 갖는다 — 처리 단계가 진행되거나(Extracted/Refined/Memorized) ResetToSource() 하면 둘 다 지워진다. 반대로 sync 상태 전이는 어느 쪽도 지우지 않는다(MarkInSync 포함). 따라서 FirstError != null을 "지금 고장난 엔트리"로 읽지 말 것 — 그 판정은 Stage/SyncStatus로 한다.
  • 이전 버전이 쓴 meta.jsonLastErrorFirstError로 승계한다(한 번만 실패한 엔트리에서는 같은 값).
  • ChangeDetectionResult에도 같은 두 필드가 실린다.

엔트리 레이아웃

엔트리 디렉터리에는 작업 산출물(레코드·추출 텍스트·이미지)이 들어가고, git이 추적하는 저장소는 그 아래 vault/ 하나다. 작업 산출물은 저장소 바깥이라 무시 규칙의 대상이 아니며, 따라서 엔트리 수준에 ignore 파일을 두지 않는다 — 저장소 바깥의 ignore 파일은 git이 읽지 않는다.

0.8.0 breaking — 위 이유로 효과가 없던 VaultEntry.GitignorePathIVaultStorageService.CreateGitignoreAsync가 제거됐다. 대체 API는 없다(생성하던 파일 자체가 무의미했다). 호출부가 있으면 지우면 된다.

Damaged records

엔트리 레코드(meta.json)는 임시 파일에 쓴 뒤 제자리 교체된다. 동시 writer가 있어도 어느 레코드가 이길지만 정해지고 둘이 섞이지 않으며, 중단된 쓰기가 반쪽 레코드를 남기지 않는다.

읽을 수 없는 레코드는 없는 레코드와 구분된다.

// 없음 → null. 존재하지만 읽을 수 없음 → VaultRecordUnreadableException
var entry = VaultEntry.LoadByHash(hash, vaultBasePath);

// 목록에서 빠진 레코드를 복구 대상으로 노출한다
IReadOnlyList<string> damaged = await vault.ListUnreadableAsync();
  • ListAsync()는 읽을 수 없는 레코드를 건너뛰되 경고 로그를 남긴다. 그 엔트리를 화면에 표시하거나 복구를 제안하려면 ListUnreadableAsync()가 돌려주는 엔트리 디렉터리 경로를 쓴다.
  • 두 목록은 같은 신호를 기준으로 나뉜다 — 엔트리는 정확히 한쪽에만 나타난다. 따라서 ListAsync().Count + ListUnreadableAsync().Count가 전체 엔트리 수다. 그 밖의 IO 오류는 삼켜지지 않고 전파된다(목록이 조용히 짧아지는 것이 바로 이 보고 기능이 없애려는 실패다).
  • 제자리 교체는 나가는 레코드를 스크래치 이름으로 옆에 둔 채 바꾼다. 그 스크래치 파일을 플랫폼이 치우지 못하면(읽는 쪽이 레코드를 붙들고 있으면 충분히 발생한다) 엔트리 디렉터리에 남으므로, 다음 쓰기가 치운다 — 단 진행 중인 교체가 되돌아갈 대상을 지우지 않도록 충분히 오래된 것만. 따라서 방금 끝난 동시 쓰기 직후에는 잠깐 보일 수 있고, 무한히 쌓이지는 않는다.
  • memorize/refresh처럼 레코드를 어차피 다시 쓰는 경로는 읽을 수 없는 레코드를 보고한 뒤 새로 만든다. 실패시키면 그 엔트리가 영구히 묶이기 때문이다. 단, 재생성된 레코드는 이력이 비어 있다.

Refresh 전제

refreshrefined 콘텐츠를 재인덱싱하며 재추출하지 않는다. 따라서 전제는 refined 콘텐츠의 존재이고, ProcessingStage는 그것을 함의하지 않는다 — 인덱싱할 내용이 없던 memorize는 refine 단계를 건너뛰므로 Memorized인데 refined가 없는 엔트리가 정상적으로 생기고, Error는 어떤 산출물이 남았는지 말해주지 않는다.

  • RefreshAsync는 refined 콘텐츠가 없으면 거부한다(메시지가 memorize를 지시한다). 이 전제는 가드와 파이프라인이 같은 값을 쓴다.
  • DetectChangesAsync는 refresh가 성공할 수 없는 엔트리에 Refresh를 추천하지 않고 Memorize로 낮춘다. memorize는 재추출하므로 실패했거나 빈 엔트리가 스스로 회복할 수 있다.

Image enrichment

문서에서 추출된 이미지는 파이프라인이 vault에 저장한다. 소비앱이 설명 생성기만 등록하면 그 설명이 인덱싱까지 이어진다 — 호출 시점·멱등·재시도·본문 반영·출처 노출은 파이프라인이 소유한다.

public sealed class VisionEnricher : IVaultImageEnricher
{
    public async Task<string?> DescribeAsync(VaultImageDescriptionRequest request, CancellationToken ct)
        => await _vision.CaptionAsync(request.Image.FilePath, request.DocumentText, ct);
        // null 반환 = 이번엔 실패 → 파이프라인이 다음 실행에 재시도
}

services.AddSingleton<IVaultImageEnricher, VisionEnricher>();
  • 미등록 시 종전과 동일 — 이미지는 저장되지만 설명되지 않는다 (하위 호환).
  • 멱등 — 설명은 이미지 단위로 영속된다. 재-memorize 시 이미 설명된 이미지는 생성기를 재호출하지 않는다(이미지가 바이트 동일한 한). 실패한 이미지만 다음 실행에서 재시도되며, 한 이미지의 실패가 다른 이미지나 memorize 자체를 중단시키지 않는다.
  • 출처는 메타데이터로 — 설명은 전용 청크로 인덱싱되고 chunk_kind="image_description" · image_id · image_file 메타데이터를 갖는다. 본문에 마커를 심지 않으므로 사용자에게 보여줄 때 걷어낼 것도 없다.
  • 이미지-only 문서 — 텍스트 레이어가 없는 스캔·도표 문서는 종전에 0청크로 끝났으나, 설명이 있으면 그 설명이 곧 내용으로 인덱싱된다. (텍스트도 없고 설명도 없으면 종전대로 0청크.)
  • request.DocumentText는 원문서 추출 텍스트이며, 텍스트 레이어가 없으면 null이다.

파이프라인은 벡터 스토어·GraphRAG와 같은 지점에서 청크를 인덱싱한다. DI 컨테이너에 IKeywordSearchService가 등록되어 있으면(FluxIndex SDK가 기본으로 등록하는 in-memory BM25 폴백이든, PostgreSQL/SQLite 같은 영속 백엔드든) 같은 청크가 키워드 인덱스에도 적재되어 하이브리드 검색의 세 번째 다리가 채워진다 — FluxIndex의 자체 Indexer 경로가 아니라 이 ingestion 파이프라인으로 적재하는 구성에서는, 이 배선 없이는 키워드 인덱스가 항상 비어 있다(벡터 단독 검색과 사실상 동일).

  • 미등록 시 종전과 동일 — 벡터·GraphRAG 인덱싱만 수행된다 (하위 호환).
  • GraphRAG과 달리 옵션 게이트가 없다 — 등록 자체가 신호다. 서비스가 있으면 항상 인덱싱하고, 없으면 항상 스킵한다(벡터 스토어 적재와 같은 규약).
  • 제거도 대칭RemoveAsync는 등록된 모든 백엔드(벡터 스토어·키워드 인덱스)에서 문서를 지운다.
  • VaultPipeline.SupportsKeywordIndex로 배선 여부를 확인할 수 있다.

상세 표면·경계는 CHARTER.md 참조.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on FluxFeed:

Package Downloads
IronHive.Flux.Rag

RAG tools for IronHive using FluxIndex capabilities

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.13.0 44 8/11/2026
0.12.0 88 8/6/2026
0.11.0 86 8/6/2026
0.10.0 91 8/6/2026
0.8.0 236 8/1/2026
0.6.1 116 7/31/2026
0.6.0 103 7/30/2026
0.5.0 98 7/30/2026
0.4.0 144 7/24/2026
0.3.0 97 7/24/2026
0.2.2 103 7/19/2026
0.2.1 130 7/7/2026
0.2.0 117 7/3/2026
0.1.0 137 7/2/2026