-
Notifications
You must be signed in to change notification settings - Fork 887
Extend IngestionPipeline to support processing documents without a file system reader #7488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: data-ingestion-preview2
Are you sure you want to change the base?
Changes from 2 commits
ec1d99d
dd77217
6258a67
5fd987a
991c14a
691fa74
a9b7f16
9d81ab6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -44,6 +44,38 @@ using VectorStoreWriter<string, IngestionChunkVectorRecord<string>> writer = new | |
| await writer.WriteAsync(chunks); | ||
| ``` | ||
|
|
||
| ## Using the IngestionPipeline | ||
|
|
||
| ### Processing documents from the file system | ||
|
|
||
| To process documents from the file system, create an `IngestionPipeline` and pass a reader to the `ProcessAsync` method: | ||
|
|
||
| ```csharp | ||
| using IngestionPipeline<string> pipeline = new(chunker, writer); | ||
|
|
||
| IngestionDocumentReader reader = new MarkdownReader(); | ||
| await foreach (IngestionResult result in pipeline.ProcessAsync(reader, directory, "*.md")) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you show a code sample demonstrating error handling when processing the async enumerable under the proposed model?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It could be sth like this: IngestionDocumentReader reader = new MarkdownReader();
await foreach (IngestionResult result in pipeline.ProcessAsync(reader, directory, "*.md"))
{
if (!result.Succeeded)
{
logger.Error($"Failed to process'{result.DocumentId}'.", result.Exception);
}
}
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But that doesn't process the full stream E2E right? What if I wanted to skip over the ingestion result that failed? |
||
| { | ||
| Console.WriteLine($"Processed '{result.DocumentId}'. Succeeded: {result.Succeeded}"); | ||
| } | ||
| ``` | ||
|
|
||
| ### Processing documents without a reader | ||
|
|
||
| The `IngestionPipeline` can also process documents that are already in memory, without requiring a reader: | ||
|
|
||
| ```csharp | ||
| using IngestionPipeline<string> pipeline = new(chunker, writer); | ||
|
adamsitnik marked this conversation as resolved.
Outdated
|
||
|
|
||
| IngestionDocument document = new("my-document-id"); | ||
| IngestionDocumentSection section = new("Main"); | ||
| section.Elements.Add(new IngestionDocumentHeader("# Introduction") { Level = 1 }); | ||
| section.Elements.Add(new IngestionDocumentParagraph("This is the content of my document.")); | ||
| document.Sections.Add(section); | ||
|
|
||
| IngestionDocument processedDocument = await pipeline.ProcessAsync(document); | ||
| ``` | ||
|
|
||
| ### Custom metadata | ||
|
|
||
| To store custom metadata alongside each chunk, create a type derived from `IngestionChunkVectorRecord<TChunk>` with additional properties, and a `VectorStoreWriter` subclass that overrides `SetMetadata`: | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -19,13 +19,13 @@ public async Task IngestDataAsync(DirectoryInfo directory, string searchPattern) | |||||||||||||||||||||||||||||||
| IncrementalIngestion = false, | ||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| DocumentReader reader = new(directory); | ||||||||||||||||||||||||||||||||
| using var pipeline = new IngestionPipeline<string>( | ||||||||||||||||||||||||||||||||
| reader: new DocumentReader(directory), | ||||||||||||||||||||||||||||||||
| chunker: new SemanticSimilarityChunker(embeddingGenerator, new(TiktokenTokenizer.CreateForModel("gpt-4o"))), | ||||||||||||||||||||||||||||||||
| writer: writer, | ||||||||||||||||||||||||||||||||
| loggerFactory: loggerFactory); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| await foreach (var result in pipeline.ProcessAsync(directory, searchPattern)) | ||||||||||||||||||||||||||||||||
| await foreach (var result in pipeline.ProcessAsync(reader, directory, searchPattern)) | ||||||||||||||||||||||||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the reader already encapsulates the directory, why does it also need to be passed in
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Encapsulating the directory is specific only to this particular reader implementation: Lines 5 to 19 in 2e5993e
Other readers don't do that. |
||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||
| logger.LogInformation("Completed processing '{id}'. Succeeded: '{succeeded}'.", result.DocumentId, result.Succeeded); | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.