chore: remove debug statements and update PRD
- Removed all debug print statements from prompt_calls.py and one_to_n_funcs.py - Updated PRD to reflect Phase 4 completion and recent bug fixes - Documented REIMB_TERM normalization fixes and cleanup work - Updated Phase 6 status to 25% complete (debug removal done)
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
# PRD: Standardize LLM Output Formats - Eliminate Pipe-Delimited Parsing
|
||||
|
||||
**Version:** 1.1
|
||||
**Version:** 1.2
|
||||
**Date:** February 2, 2026
|
||||
**Last Updated:** February 2, 2026 (Commit: 98554afc)
|
||||
**Status:** In Progress - Phase 2 Complete
|
||||
**Last Updated:** February 3, 2026 (Commit: a633f67c)
|
||||
**Status:** In Progress - Phase 4 Complete, Bug Fixes Applied
|
||||
**Author:** AI Assistant
|
||||
|
||||
---
|
||||
@@ -19,9 +19,11 @@
|
||||
| Phase 3: Prompt Calling Layer | ✅ Complete | 100% | All prompt_calls.py updated; code_funcs.py fixed |
|
||||
| Phase 4: Downstream Consumers | ✅ Complete | 100% | All LLM output parsing updated; testbed/QC files verified (internal data - out of scope) |
|
||||
| Phase 5: Testing | 🔲 Not Started | 0% | Integration tests, golden tests |
|
||||
| Phase 6: Cleanup & Documentation | 🔲 Not Started | 0% | Remove backward compat, docs |
|
||||
| Phase 6: Cleanup & Documentation | 🟡 In Progress | 25% | Debug statements removed, defensive checks cleaned up |
|
||||
|
||||
**Latest Commits** (after PRD update):
|
||||
- `a633f67c` - Fixed REIMB_TERM being converted to list in lesser_of_distribution; removed debug statements
|
||||
- `4c0d2930` - Updated PRD: Phase 4 now 100% complete
|
||||
- `13f3cbea` - Completed Phase 4: Fixed model_evaluation_utils.py LLM output parsing
|
||||
- `a7a32b90` - Completed Phase 3: Fixed remaining universal_json_load calls in code_funcs.py
|
||||
- `2e307347` - Updated investment_prompts.json to use JSON format instead of pipes
|
||||
@@ -40,6 +42,12 @@
|
||||
- Verified testbed/QC files process internal data (out of scope per PRD)
|
||||
- `aarete_derived.py` has dual-format support (intentional for backward compatibility during transition)
|
||||
|
||||
**Recent Bug Fixes** (Commit: a633f67c):
|
||||
- Fixed `REIMB_TERM` being converted to list in `lesser_of_distribution` - parser now extracts string from list when needed
|
||||
- Normalized `SERVICE_TERM` and `REIMB_TERM` upstream in `prompt_reimbursement_primary` to ensure strings
|
||||
- Removed defensive normalization checks that are no longer needed (CODE_EXPLICIT, CODE_CATEGORY, CODE_IMPLICIT, FILL_BILL_TYPE)
|
||||
- Removed all debug print statements from `prompt_calls.py` and `one_to_n_funcs.py`
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
@@ -2890,7 +2898,7 @@ def test_parsing_performance():
|
||||
|
||||
---
|
||||
|
||||
## Implementation Status Summary (Last Updated: Feb 3, 2026)
|
||||
## Implementation Status Summary (Last Updated: Feb 3, 2026 - Commit: a633f67c)
|
||||
|
||||
### ✅ Completed Work
|
||||
|
||||
@@ -2912,11 +2920,12 @@ def test_parsing_performance():
|
||||
- ✅ `src/pipelines/shared/preprocessing/hybrid_smart_chunking_funcs.py` - All updated
|
||||
- ⚠️ `src/codes/code_funcs.py` - 2 remaining `universal_json_load` calls (lines 498, 856)
|
||||
|
||||
**Phase 4: Downstream Consumers** (60% Complete)
|
||||
**Phase 4: Downstream Consumers** (100% Complete)
|
||||
- ✅ `src/utils/crosswalk_utils.py` - Updated to handle JSON lists
|
||||
- ✅ `src/pipelines/shared/extraction/dynamic_funcs.py` - Updated
|
||||
- ✅ `src/pipelines/shared/postprocessing/postprocessing_funcs.py` - Major cleanup (113 lines changed)
|
||||
- ✅ `src/pipelines/shared/postprocessing/aarete_derived.py` - Dual-format support implemented (intentional backward compatibility)
|
||||
- ✅ `src/testbed/model_evaluation_utils.py` - Updated to use JSON parsers (Commit: 13f3cbea)
|
||||
|
||||
### ⏳ Remaining Work
|
||||
|
||||
@@ -2939,7 +2948,9 @@ def test_parsing_performance():
|
||||
- [ ] Run full test suite
|
||||
- [ ] Manual QA testing
|
||||
|
||||
**Phase 6: Cleanup & Documentation** (0% complete)
|
||||
**Phase 6: Cleanup & Documentation** (Partial - 25% complete)
|
||||
- [x] Removed all debug print statements from `prompt_calls.py` and `one_to_n_funcs.py` (Commit: a633f67c)
|
||||
- [x] Removed defensive normalization checks that are no longer needed (Commit: a633f67c)
|
||||
- [ ] Remove backward compatibility code (if desired)
|
||||
- [ ] Update documentation
|
||||
- [ ] Code review
|
||||
@@ -2956,9 +2967,11 @@ def test_parsing_performance():
|
||||
### 🎯 Key Achievements
|
||||
|
||||
1. **Architectural Improvement**: All prompt templates now return `(prompt, parser)` tuples, eliminating ambiguity
|
||||
2. **Code Reduction**: Net reduction of ~350 lines through cleanup
|
||||
2. **Code Reduction**: Net reduction of ~400 lines through cleanup
|
||||
3. **Consistency**: All prompt calling code uses the same pattern
|
||||
4. **Backward Compatibility**: `aarete_derived.py` maintains dual-format support during transition
|
||||
5. **Data Normalization**: SERVICE_TERM and REIMB_TERM normalized upstream to ensure consistent string format
|
||||
6. **Bug Fixes**: Fixed REIMB_TERM list conversion in lesser_of_distribution, removed unnecessary defensive checks
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -126,11 +126,6 @@ def prompt_reimbursement_primary(
|
||||
|
||||
try:
|
||||
llm_answer_final = _parser(llm_answer_raw)
|
||||
|
||||
# DEBUG: Print raw parsed output
|
||||
print(f"\n[DEBUG REIMBURSEMENT_PRIMARY] Parsed output for {filename}:")
|
||||
print(llm_answer_final)
|
||||
print()
|
||||
except ValueError as e:
|
||||
logging.error(f"Error parsing LLM response: {e}")
|
||||
logging.error(f"Raw LLM output: {llm_answer_raw}")
|
||||
@@ -179,7 +174,7 @@ def prompt_fee_schedule_breakout(
|
||||
Note: Field definitions are now included in FEE_SCHEDULE_BREAKOUT_INSTRUCTION() for caching.
|
||||
"""
|
||||
# Normalize FEE_SCHEDULE to string before using in prompt (should already be normalized from prompt_methodology_breakout)
|
||||
fee_schedule = methodology_breakout_dict.get("FEE_SCHEDULE", "")
|
||||
fee_schedule = methodology_breakout_dict.get("FEE_SCHEDULE", "")
|
||||
prompt, _parser = prompt_templates.FEE_SCHEDULE_BREAKOUT(
|
||||
reimbursement_method,
|
||||
fee_schedule,
|
||||
@@ -700,17 +695,17 @@ def prompt_lesser_of_distribution(
|
||||
return reimb_term # Return original term unchanged
|
||||
else:
|
||||
llm_answer_final = _parser(llm_answer_raw)
|
||||
|
||||
# DEBUG: Print raw parsed output
|
||||
print(f"\n[DEBUG prompt_lesser_of_distribution] Raw parsed output:")
|
||||
print(llm_answer_final)
|
||||
|
||||
logging.debug(
|
||||
f"Applied lesser-of to '{service_term}' on page {page_num}: "
|
||||
f"{reimb_term} → {llm_answer_final[:60]}..."
|
||||
)
|
||||
|
||||
return llm_answer_final[0] if isinstance(llm_answer_final, list) else llm_answer_final
|
||||
return (
|
||||
llm_answer_final[0]
|
||||
if isinstance(llm_answer_final, list)
|
||||
else llm_answer_final
|
||||
)
|
||||
|
||||
|
||||
def prompt_lesser_of_check(
|
||||
|
||||
@@ -98,13 +98,6 @@ def reimbursement_level(
|
||||
reimbursement_primary_answers, constants, filename
|
||||
)
|
||||
|
||||
# ============================================================================
|
||||
# DEBUG: Print reimbursement_primary_answers after filtering
|
||||
# ============================================================================
|
||||
print(f"\n[DEBUG reimbursement_level] After filtering (line 101):")
|
||||
print(reimbursement_primary_answers)
|
||||
# ============================================================================
|
||||
|
||||
return reimbursement_primary_answers
|
||||
|
||||
|
||||
@@ -130,7 +123,6 @@ def clean_reimbursement_primary(
|
||||
"""
|
||||
if reimbursement_primary_answers: # If any reimbursements found
|
||||
|
||||
|
||||
# If needed, add Reimbursement Splitting here
|
||||
|
||||
# If needed, add deduplication here
|
||||
@@ -339,17 +331,9 @@ def methodology_breakout_single_row(
|
||||
list[dict]: Updated list with methodology breakout details and fee schedule information.
|
||||
"""
|
||||
|
||||
# DEBUG: Check what answer_dict contains
|
||||
print(f"\n[DEBUG methodology_breakout_single_row] answer_dict REIMB_TERM: {repr(answer_dict.get('REIMB_TERM'))} (type: {type(answer_dict.get('REIMB_TERM')).__name__})")
|
||||
print(f"[DEBUG methodology_breakout_single_row] answer_dict SERVICE_TERM: {repr(answer_dict.get('SERVICE_TERM'))} (type: {type(answer_dict.get('SERVICE_TERM')).__name__})")
|
||||
|
||||
reimb_term = answer_dict.get("REIMB_TERM", "")
|
||||
service_term = answer_dict.get("SERVICE_TERM", "")
|
||||
|
||||
# DEBUG: Check what we extracted
|
||||
print(f"[DEBUG methodology_breakout_single_row] Extracted reimb_term: {repr(reimb_term)} (type: {type(reimb_term).__name__})")
|
||||
print(f"[DEBUG methodology_breakout_single_row] Extracted service_term: {repr(service_term)} (type: {type(service_term).__name__})\n")
|
||||
|
||||
|
||||
methodology_breakout_questions = FieldSet(
|
||||
config.FIELD_JSON_PATH, field_type="methodology_breakout"
|
||||
)
|
||||
@@ -806,18 +790,22 @@ def one_to_n_cleaning(
|
||||
lob_program_rel = answer_dict["LOB_PROGRAM_RELATIONSHIP"]
|
||||
if isinstance(lob_program_rel, list):
|
||||
# If list, take first element (shouldn't happen, but defensive)
|
||||
answer_dict["LOB_PROGRAM_RELATIONSHIP"] = str(lob_program_rel[0]) if lob_program_rel else "Exclusive"
|
||||
answer_dict["LOB_PROGRAM_RELATIONSHIP"] = (
|
||||
str(lob_program_rel[0]) if lob_program_rel else "Exclusive"
|
||||
)
|
||||
elif lob_program_rel is not None:
|
||||
answer_dict["LOB_PROGRAM_RELATIONSHIP"] = str(lob_program_rel)
|
||||
else:
|
||||
answer_dict["LOB_PROGRAM_RELATIONSHIP"] = "Exclusive"
|
||||
|
||||
|
||||
# LOB_PRODUCT_RELATIONSHIP should be a string (not a list)
|
||||
if "LOB_PRODUCT_RELATIONSHIP" in answer_dict:
|
||||
lob_product_rel = answer_dict["LOB_PRODUCT_RELATIONSHIP"]
|
||||
if isinstance(lob_product_rel, list):
|
||||
# If list, take first element (shouldn't happen, but defensive)
|
||||
answer_dict["LOB_PRODUCT_RELATIONSHIP"] = str(lob_product_rel[0]) if lob_product_rel else "Exclusive"
|
||||
answer_dict["LOB_PRODUCT_RELATIONSHIP"] = (
|
||||
str(lob_product_rel[0]) if lob_product_rel else "Exclusive"
|
||||
)
|
||||
elif lob_product_rel is not None:
|
||||
answer_dict["LOB_PRODUCT_RELATIONSHIP"] = str(lob_product_rel)
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user