afb6d5185d
Feature/lesser table caching refactor hybrid * chore: Remove unused duplicate main.py from shared pipeline * fix: Correct crosswalk paths in aarete_derived.py * chore: Remove unused documentation files from fieldExtraction * docs: Add documentation files to documentation folder * docs: Update README with uv setup, expanded project structure, and branching conventions * docs: Add uv installation steps with Ubuntu/WSL emphasis * Enable prompt caching for all remaining LLM calls - Add _INSTRUCTION() functions for: EXHIBIT_HEADER, EXHIBIT_LINKAGE, EXHIBIT_TITLE_MATCH, DATE_FIX, DERIVED_TERM_DATE, CHECK_PROVIDER_NAME_MATCH, SPECIAL_CASE_ASSIGNMENT - Update all invoke_claude() calls in saas and clover pipelines to use cache=True with corresponding _INSTRUCTION() functions - Add new instructions to get_cacheable_instructions() for cache warming - Update tests for new instruction functions Functions now using caching: - prompt_exhibit_level - prompt_exhibit_lesser (EXHIBIT_LEVEL_LESSER_OF) - prompt_fee_schedule_breakout - prompt_grouper_breakout - prompt_special_case_assignment - prompt_exhibit_linkage - prompt_exhibit_header - prompt_smart_chunked (ONE_TO_ONE templates) - prompt_date_fix - prompt_derived_term_date - prompt_exhibit_title_match - provider_name_match_check 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Reorder * feat: Add bcbs_promise client pipeline with OFFSET_TERM extraction - Add new bcbs_promise client with HSC-based OFFSET_TERM field extraction - Extract full paragraph text of offset/recoupment provisions from contracts - Derive OFFSET_INDICATOR (Y/N) from OFFSET_TERM presence - Fix reorder_columns to preserve extra columns not in COLUMN_ORDER - Update QC/QA output path to outputs/qc_qa/ * fix: Update dev deps and test assertions for QC/QA output path - Add pytest/pytest-mock to dev dependencies for mypy type checking - Update test assertions to expect outputs/qc_qa instead of qa_qc_output * style: Apply black formatting to prompt_templates.py * Merge main, move scripts * Archive some scripts * update py version * remove .py version file * Remove ASCII characters * Restore testbed code * restore tracking * Update testbed metrics * Enable prompt caching for CODE_LAST_CHECK, FILL_BILL_TYPE, DUAL_LOB_CHECK, and GROUPER_BREAKOUT - Add CODE_LAST_CHECK_INSTRUCTION() for service specificity classification - Add FILL_BILL_TYPE_INSTRUCTION() for bill type code determination - Add DUAL_LOB_CHECK_INSTRUCTION() for Medicare/Medicaid classification - Update code_funcs.py to use caching for CODE_LAST_CHECK, FILL_BILL_TYPE, GROUPER_BREAKOUT - Update postprocessing_funcs.py to use caching for DUAL_LOB_CHECK - Add new instructions to get_cacheable_instructions() for cache warming - Add unit tests for new instruction functions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Fix postprocessing_funcs to remove invalid columns * Merge branch 'main' into feature/lesser-table-caching-refactor-hybrid * Revert prompt caching changes from aed1b73c * update formatting * Update imports Approved-by: Sha Brown Approved-by: Praneel Panchigar
192 lines
7.3 KiB
Plaintext
192 lines
7.3 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Setting up imports that we will need, particularly - csv, boto3, ThreadPoolExecutor and pandas"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 36,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import csv\n",
|
|
"import boto3\n",
|
|
"from concurrent.futures import ThreadPoolExecutor\n",
|
|
"from botocore.exceptions import ClientError\n",
|
|
"import pandas as pd\n",
|
|
"\n",
|
|
"s3 = boto3.Session(profile_name='temp_cred').client('s3')"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"This function use pagination to iterate through all objects in the specified s3 bucket and builds a file cache with all s3 keys. This is meant to be run only-once and is expected to take 8-10 mins to complete"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 37,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"def list_all_files(bucket_name):\n",
|
|
" all_keys = []\n",
|
|
" try:\n",
|
|
" paginator = s3.get_paginator('list_objects_v2')\n",
|
|
" for page in paginator.paginate(Bucket=bucket_name):\n",
|
|
" if 'Contents' in page:\n",
|
|
" all_keys.extend([item['Key'] for item in page['Contents']])\n",
|
|
" except ClientError as e:\n",
|
|
" print(f\"Error listing files in bucket {bucket_name}: {e}\")\n",
|
|
" return all_keys\n",
|
|
"\n",
|
|
"bucket_name = 'centene-national-contracting-files'\n",
|
|
"all_keys = list_all_files(bucket_name)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Searching v1 - using complete matching of the filenames in the s3 bucket. If ```copy``` is set to ```True```, then the files found will also be copied to the specified prefix."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 44,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"CSV processing completed.\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"# Complete matching\n",
|
|
"def check_file_in_bucket(filename, all_keys):\n",
|
|
" locations = [key for key in all_keys if (key.lower().endswith(filename.lower()))]\n",
|
|
" if copy:\n",
|
|
" for l in locations:\n",
|
|
" s3.copy_object(\n",
|
|
" CopySource={'Bucket': bucket_name, 'Key': l},\n",
|
|
" Bucket=bucket_name,\n",
|
|
" Key=destination_prefix + \"/\" + filename\n",
|
|
" )\n",
|
|
" exists = bool(locations)\n",
|
|
" return filename, exists, locations\n",
|
|
"\n",
|
|
"def process_csv(input_csv, output_csv):\n",
|
|
" \n",
|
|
" with open(input_csv, mode='r', newline='', encoding='utf8') as infile, open(output_csv, mode='w', newline='', encoding='utf8') as outfile:\n",
|
|
" reader = csv.reader(infile)\n",
|
|
" writer = csv.writer(outfile)\n",
|
|
" writer.writerow(['File Name', 'exists', 'locations']) # Write header\n",
|
|
"\n",
|
|
" with ThreadPoolExecutor(max_workers = 50) as executor:\n",
|
|
" futures = [executor.submit(check_file_in_bucket, row[0][:-4] + file_extension, all_keys) for row in reader]\n",
|
|
" \n",
|
|
" for future in futures:\n",
|
|
" filename, exists, locations = future.result()\n",
|
|
" writer.writerow([filename, exists, locations])\n",
|
|
"\n",
|
|
"# Input csv with all file names listed without extension in the first column\n",
|
|
"input_csv = '../CNC/batch4/batch4_missing_files_2.csv'\n",
|
|
"# Path to output that will be generated with the following columns = File Name, exists, locations\n",
|
|
"output_csv = '../CNC/batch4/batch4_missing_files_2_paths_txt.csv'\n",
|
|
"# If copy = True, the files found will be copied over to this destination in s3 (User Keys needs copy permission)\n",
|
|
"destination_prefix = 'batch_4_priority_files/hotfix_diff_121124/TXT_FILES'\n",
|
|
"copy = True\n",
|
|
"# File Extension that will be added to the end of the file names - to look for\n",
|
|
"file_extension = '.txt'\n",
|
|
"\n",
|
|
"process_csv(input_csv, output_csv)\n",
|
|
"print(\"CSV processing completed.\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"Searching v2 - using partial matching of the filenames in the s3 bucket. In this specific case, we check the first 10 and last 10 characters of the filename (This logic can be changed in the 3rd line, as required). If ```copy``` is set to ```True```, then the files found will also be copied to the specified prefix."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Partial matching\n",
|
|
"def check_file_in_bucket(filename, all_keys):\n",
|
|
" locations = [key for key in all_keys if (filename[:10].lower() in key.lower() and key.lower().endswith(filename[-10:].lower()))]\n",
|
|
" if copy:\n",
|
|
" for l in locations:\n",
|
|
" s3.copy_object(\n",
|
|
" CopySource={'Bucket': bucket_name, 'Key': l},\n",
|
|
" Bucket=bucket_name,\n",
|
|
" Key=destination_prefix + \"/\" + filename\n",
|
|
" )\n",
|
|
" exists = bool(locations)\n",
|
|
" return filename, exists, locations\n",
|
|
"\n",
|
|
"def process_csv(input_csv, output_csv):\n",
|
|
" \n",
|
|
" with open(input_csv, mode='r', newline='', encoding='utf8') as infile, open(output_csv, mode='w', newline='', encoding='utf8') as outfile:\n",
|
|
" reader = csv.reader(infile)\n",
|
|
" writer = csv.writer(outfile)\n",
|
|
" writer.writerow(['File Name', 'exists', 'locations']) # Write header\n",
|
|
"\n",
|
|
" with ThreadPoolExecutor(max_workers = 50) as executor:\n",
|
|
" futures = [executor.submit(check_file_in_bucket, row[0][:-4] + file_extension, all_keys) for row in reader]\n",
|
|
" \n",
|
|
" for future in futures:\n",
|
|
" filename, exists, locations = future.result()\n",
|
|
" writer.writerow([filename, exists, locations])\n",
|
|
"\n",
|
|
"# Input csv with all file names listed without extension in the first column\n",
|
|
"input_csv = '../CNC/batch4/batch4_missing_files_2.csv'\n",
|
|
"# Path to output that will be generated with the following columns = File Name, exists, locations\n",
|
|
"output_csv = '../CNC/batch4/batch4_missing_files_2_paths_txt.csv'\n",
|
|
"# If copy = True, the files found will be copied over to this destination in s3 (User Keys needs copy permission)\n",
|
|
"destination_prefix = 'batch_4_priority_files/hotfix_diff_121124/TXT_FILES'\n",
|
|
"copy = True\n",
|
|
"# File Extension that will be added to the end of the file names - to look for\n",
|
|
"file_extension = '.txt'\n",
|
|
"\n",
|
|
"process_csv(input_csv, output_csv)\n",
|
|
"print(\"CSV processing completed.\")"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": ".venv",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.12.3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 2
|
|
}
|