Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion application/single_app/config.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -97,7 +97,7 @@
EXECUTOR_TYPE = 'thread'
EXECUTOR_MAX_WORKERS = 30
SESSION_TYPE = 'filesystem'
VERSION = "0.250.066"
VERSION = "0.250.067"
IS_DEVELOPMENT = is_development_env_enabled()

SESSION_COOKIE_SAMESITE = os.getenv('SESSION_COOKIE_SAMESITE', 'Lax')
Expand Down
111 changes: 111 additions & 0 deletions application/single_app/functions_document_comparison.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -224,6 +224,117 @@ def _format_comparison_coverage_summary(coverage, left_document_name, right_docu
return '\n'.join(lines)


def run_evidence_document_comparison(
comparison_prompt,
left_source,
right_sources,
invoke_prompt,
activity_callback=None,
):
"""Run the established one-left-to-many comparison over native evidence envelopes."""
normalized_prompt = str(comparison_prompt or '').strip()
if not normalized_prompt or not callable(invoke_prompt):
raise ValueError('A comparison prompt and callable invoke_prompt handler are required.')

left_source = left_source if isinstance(left_source, dict) else {}
right_sources = [source for source in list(right_sources or []) if isinstance(source, dict)]
left_name = str(left_source.get('document_name') or 'Source').strip() or 'Source'
left_summary = str(left_source.get('summary') or '').strip()
comparison_items = []
compared_targets = []
failed_targets = []

for comparison_index, right_source in enumerate(right_sources, start=1):
right_name = str(right_source.get('document_name') or f'Target {comparison_index}').strip() or f'Target {comparison_index}'
right_status = str(right_source.get('status') or '').strip().lower()
if right_status not in {'completed', 'partial'} or not left_summary:
failed_targets.append(right_name)
continue

if callable(activity_callback):
activity_callback({
'type': 'comparison_started',
'left_document_id': left_source.get('document_id'),
'left_document_name': left_name,
'right_document_id': right_source.get('document_id'),
'right_document_name': right_name,
'comparison_index': comparison_index,
'comparison_count': len(right_sources),
})
pairwise_text = str(invoke_prompt(
_build_pairwise_comparison_prompt(
normalized_prompt,
left_name,
right_name,
left_summary,
str(right_source.get('summary') or ''),
),
stage='comparison',
metadata={
'comparison_index': comparison_index,
'comparison_count': len(right_sources),
'left_document_id': left_source.get('document_id'),
'right_document_id': right_source.get('document_id'),
},
) or '').strip()
if not pairwise_text:
failed_targets.append(right_name)
continue
compared_targets.append(right_name)
comparison_items.append({
'right_document_id': right_source.get('document_id'),
'right_document_name': right_name,
'text': pairwise_text,
})
if callable(activity_callback):
activity_callback({
'type': 'comparison_completed',
'left_document_id': left_source.get('document_id'),
'left_document_name': left_name,
'right_document_id': right_source.get('document_id'),
'right_document_name': right_name,
'comparison_index': comparison_index,
'comparison_count': len(right_sources),
})

if not comparison_items:
final_reply = 'No target comparison could be completed from the available source evidence.'
elif len(comparison_items) == 1:
final_reply = comparison_items[0]['text']
else:
final_reply = str(invoke_prompt(
_build_comparison_reduction_prompt(normalized_prompt, left_name, comparison_items),
stage='comparison_reduction',
metadata={'comparison_count': len(comparison_items), 'left_document_id': left_source.get('document_id')},
) or '').strip() or 'The completed target comparisons could not be reduced into a final response.'

evidence_engines = sorted({
str(source.get('engine') or 'unknown')
for source in [left_source, *right_sources]
})
conclusion_level = 'aggregate or narrative'
if all(str(source.get('source_kind') or '') == 'tabular' for source in [left_source, *right_sources]):
conclusion_level = 'aggregate; row-level conclusions require validated structured table operations'
coverage_note = (
f'\n\n## Comparison Coverage\n- Targets compared: {len(compared_targets)}\n'
f'- Failed or partial targets: {len(failed_targets)}\n'
f'- Evidence engines: {", ".join(evidence_engines)}\n'
f'- Conclusion level: {conclusion_level}'
)
return {
'reply': f'{final_reply}{coverage_note}',
'analysis_reply': final_reply,
'coverage': {'document_count': 1 + len(right_sources), 'partial_coverage': bool(failed_targets), 'failed_targets': failed_targets},
'documents': [left_source, *right_sources],
'left_document': {'document_id': left_source.get('document_id'), 'document_name': left_name},
'right_documents': [
{'document_id': source.get('document_id'), 'document_name': source.get('document_name')}
for source in right_sources
],
'comparison_items': comparison_items,
}


def run_document_comparison(
user_id,
comparison_prompt,
Expand Down
15 changes: 15 additions & 0 deletions application/single_app/functions_settings.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -233,6 +233,19 @@ def is_mixed_source_analyze_all_enabled(settings):
)


def is_cross_format_compare_enabled(settings):
"""Return whether Phase 4 native mixed-source Compare behavior is enabled."""
return bool((settings or {}).get('enable_cross_format_compare', False))


def is_cross_format_compare_one_to_many_enabled(settings):
"""Return whether the separately staged one-to-many mixed-target rollout is enabled."""
return bool(
(settings or {}).get('enable_cross_format_compare', False)
and (settings or {}).get('enable_cross_format_compare_one_to_many', False)
)


def is_mixed_source_relevance_candidates_enabled(settings):
"""Return whether Phase 2 relevance-mode table candidates are enabled."""
return bool(
Expand DownExpand Up@@ -795,6 +808,8 @@ def get_settings(use_cosmos=False, include_source=False):
'enable_mixed_source_relevance_candidates': False,
'enable_mixed_source_analyze': False,
'enable_mixed_source_analyze_all': False,
'enable_cross_format_compare': False,
'enable_cross_format_compare_one_to_many': False,
'max_rounds_per_agent': 1,
'workflow_max_auto_invoke_attempts': 60,
'enable_semantic_kernel': False,
Expand Down
Loading