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:
ppanchigar
2026-02-03 17:27:45 -06:00
parent a633f67c62
commit 3c89aecfaf
3 changed files with 35 additions and 39 deletions
+21 -8
View File
@@ -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
---
+6 -11
View File
@@ -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: