-
Notifications
You must be signed in to change notification settings - Fork 0
Add comprehensive document metadata support in Knowledge Base workflow node #5
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
Changes from all commits
5cef611
163a924
8a31d52
eb1b8c5
7997ef2
c85b57f
c0607d4
15777a6
cf198ef
f566da5
1df04fb
7759ab0
67016a7
96b7f2c
8574d3e
c844453
6784f1a
eba2f06
14bbb1d
5886466
67a798f
26248e3
890755d
a4cd1fb
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 |
|---|---|---|
|
|
@@ -41,6 +41,8 @@ | |
| Dataset, | ||
| DatasetAutoDisableLog, | ||
| DatasetCollectionBinding, | ||
| DatasetMetadata, | ||
| DatasetMetadataBinding, | ||
| DatasetPermission, | ||
| DatasetPermissionEnum, | ||
| DatasetProcessRule, | ||
|
|
@@ -1902,6 +1904,36 @@ def save_document_with_dataset_id( | |
| else default_retrieval_model | ||
| ) | ||
|
|
||
| # Handle metadata configuration | ||
| # 1. Enable built-in metadata if requested | ||
| if knowledge_config.enable_built_in_metadata and not dataset.built_in_field_enabled: | ||
| dataset.built_in_field_enabled = True | ||
| db.session.add(dataset) | ||
|
|
||
| # 2. Process custom metadata - validate and build dict | ||
| custom_metadata: dict = {} | ||
| metadata_bindings_to_create: list[tuple[str, str]] = [] # (metadata_id, metadata_name) | ||
| if knowledge_config.doc_metadata: | ||
| # Batch fetch all metadata definitions to avoid N+1 query | ||
| metadata_ids = [item.metadata_id for item in knowledge_config.doc_metadata] | ||
| metadata_defs = ( | ||
| db.session.query(DatasetMetadata) | ||
| .filter( | ||
| DatasetMetadata.id.in_(metadata_ids), | ||
| DatasetMetadata.dataset_id == dataset.id, | ||
| ) | ||
| .all() | ||
| ) | ||
| metadata_map = {md.id: md for md in metadata_defs} | ||
|
|
||
| for item in knowledge_config.doc_metadata: | ||
| # Validate metadata_id belongs to this dataset | ||
| metadata_def = metadata_map.get(item.metadata_id) | ||
| if not metadata_def: | ||
| raise ValueError(f"Metadata with id '{item.metadata_id}' not found in this dataset") | ||
| custom_metadata[metadata_def.name] = item.value | ||
| metadata_bindings_to_create.append((item.metadata_id, metadata_def.name)) | ||
|
|
||
| documents = [] | ||
| if knowledge_config.original_document_id: | ||
| document = DocumentService.update_document_with_dataset_id(dataset, knowledge_config, account) | ||
|
|
@@ -2024,6 +2056,7 @@ def save_document_with_dataset_id( | |
| account, | ||
| file.name, | ||
| batch, | ||
| custom_metadata=custom_metadata or None, | ||
| ) | ||
| db.session.add(document) | ||
| db.session.flush() | ||
|
|
@@ -2076,6 +2109,7 @@ def save_document_with_dataset_id( | |
| account, | ||
| truncated_page_name, | ||
| batch, | ||
| custom_metadata=custom_metadata or None, | ||
| ) | ||
| db.session.add(document) | ||
| db.session.flush() | ||
|
|
@@ -2116,6 +2150,7 @@ def save_document_with_dataset_id( | |
| account, | ||
| document_name, | ||
| batch, | ||
| custom_metadata=custom_metadata or None, | ||
| ) | ||
| db.session.add(document) | ||
| db.session.flush() | ||
|
|
@@ -2124,6 +2159,20 @@ def save_document_with_dataset_id( | |
| position += 1 | ||
| db.session.commit() | ||
|
|
||
| # Create DatasetMetadataBinding records for custom metadata | ||
| if metadata_bindings_to_create and document_ids: | ||
| for doc_id in document_ids: | ||
| for metadata_id, _ in metadata_bindings_to_create: | ||
| binding = DatasetMetadataBinding( | ||
| tenant_id=dataset.tenant_id, | ||
| dataset_id=dataset.id, | ||
| document_id=doc_id, | ||
| metadata_id=metadata_id, | ||
| created_by=account.id, | ||
| ) | ||
| db.session.add(binding) | ||
| db.session.commit() | ||
|
|
||
| # trigger async task | ||
| if document_ids: | ||
| DocumentIndexingTaskProxy(dataset.tenant_id, dataset.id, document_ids).delay() | ||
|
|
@@ -2436,6 +2485,7 @@ def build_document( | |
| account: Account, | ||
| name: str, | ||
| batch: str, | ||
| custom_metadata: dict | None = None, | ||
| ): | ||
| # Set need_summary based on dataset's summary_index_setting | ||
| need_summary = False | ||
|
|
@@ -2466,6 +2516,9 @@ def build_document( | |
| BuiltInField.last_update_date: datetime.datetime.now(datetime.UTC).strftime("%Y-%m-%d %H:%M:%S"), | ||
| BuiltInField.source: data_source_type, | ||
| } | ||
| # Merge custom metadata if provided | ||
| if custom_metadata: | ||
| doc_metadata.update(custom_metadata) | ||
|
Comment on lines
+2520
to
+2521
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 doc_metadata: | ||
| document.doc_metadata = doc_metadata | ||
| return document | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code attempts to iterate over
node_data_obj.doc_metadataassuming it is iterable. Ifdoc_metadataisNoneor not an iterable, theforloop will raise aTypeError, breaking the program execution.Ensure
node_data_obj.doc_metadatais always an iterable before the loop, or add a conditional check or default to an empty iterable to prevent this error.