Merged in field-group/code-primary (pull request #389)

Field group/code primary

* Code breakout function

* Merged main into field-group/code-primary

* Update prompts

* Add admit type

* Merged main into field-group/code-primary

* Updated code primary prompts

* Updated code primary prompt template


Approved-by: Alex Galarce
This commit is contained in:
Katon Minhas
2025-02-11 15:40:55 +00:00
parent 524968f09f
commit d442ec275a
3 changed files with 67 additions and 18 deletions
@@ -242,6 +242,35 @@ def get_methodology_breakout(reimbursement_primary_answers: list[dict], filename
return methodology_breakout_answers
def get_code_breakout(answer_dicts: list[dict], filename: str):
code_primary_questions = FieldSet(file_path=config.FIELD_JSON_PATH, field_type="code_primary_breakout").get_prompt_dict()
code_breakout_answers = []
already_seen = {}
for answer_dict in answer_dicts:
service = answer_dict.get("CONTRACT_SERVICE_CD_OR_DESC")
if service:
code_answer_dict = already_seen.setdefault(
service,
string_utils.universal_json_load(
llm_utils.invoke_claude(
investment_prompts.CODE_PRIMARY_BREAKOUT(service, code_primary_questions),
config.MODEL_ID_CLAUDE35_SONNET,
filename
)
)
)
else:
code_answer_dict = {}
code_breakout_answers.append({**answer_dict, **code_answer_dict})
return code_breakout_answers
def reimbursement_tin_npi(exhibit_chunk: str, reimbursement_level_fields: FieldSet) -> tuple[dict, FieldSet]:
"""
Extracts Reimbursement-Level TIN and NPI values from the given exhibit chunk using regex patterns. For multiple TIN/NPIs in Exhibit, assigns the field to be run as part of Reimbursement-Level Primary
@@ -296,8 +325,9 @@ def reimbursement_level(exhibit_text, filename, reimbursement_level_fields):
# Later, we will only run methodology breakout for those without certain carveout indicators. We will run carveout-specific breakouts for the others
methodology_breakout_answers = get_methodology_breakout(carveout_answers, filename)
code_breakout_answers = get_code_breakout(methodology_breakout_answers, filename)
return methodology_breakout_answers
return code_breakout_answers
@@ -364,8 +364,8 @@
{
"field_name": "CPT4_PROC_CD",
"relationship": "one_to_n",
"field_type": "TBD",
"prompt": "TBD"
"field_type": "code_primary_breakout",
"prompt": "Identify all Procedure (CPT or HCPCS) Codes in the text: - CPT codes are exactly 5 numeric digits (00100-99999) - HCPCS codes are 1 letter followed by 4 numbers (A0000-V9999)."
},
{
"field_name": "CPT4_PROC_DESC",
@@ -376,8 +376,8 @@
{
"field_name": "CPT4_PROC_MOD",
"relationship": "one_to_n",
"field_type": "TBD",
"prompt": "TBD"
"field_type": "code_primary_breakout",
"prompt": "Identify all CPT code modifiers in the text: Identify CPT modifiers in the text: - Modifiers are 2-character codes (alphanumeric) appended to the end of a five-character Procedure code."
},
{
"field_name": "CPT4_PROC_MOD_DESC",
@@ -388,8 +388,8 @@
{
"field_name": "REVENUE_CD",
"relationship": "one_to_n",
"field_type": "TBD",
"prompt": "TBD"
"field_type": "code_primary_breakout",
"prompt": "Identify all Revenue codes (Rev codes) in the text: - 3-4 digit numeric codes - May have 'X' as a wildcard character - Start with digits 0-9."
},
{
"field_name": "REVENUE_CD_DESC",
@@ -398,10 +398,10 @@
"prompt": "TBD"
},
{
"field_name": "DIAG_CD_01",
"field_name": "DIAG_CD_LIST",
"relationship": "one_to_n",
"field_type": "TBD",
"prompt": "TBD"
"field_type": "code_primary_breakout",
"prompt": "Identify diagnosis codes (ICD-10) in the text: - 3-7 characters in length - First character must be a letter - Characters 2-3 must be numbers - Characters 4-7 (if present) can be numbers or letters."
},
{
"field_name": "DIAG_CD_DESC",
@@ -418,8 +418,8 @@
{
"field_name": "FACILITY_GROUPER_CD",
"relationship": "one_to_n",
"field_type": "TBD",
"prompt": "TBD"
"field_type": "code_primary_breakout",
"prompt": "Identify grouper codes (DRGs) in the text: - Basic format: 3 digits (like 123) - May include severity/risk indicators (like 123-4) - May include decimal points (like 123.45) - Maximum length of 7 characters."
},
{
"field_name": "FACILITY_GROUPER_DESC",
@@ -430,8 +430,8 @@
{
"field_name": "LINE_NDC_NUM",
"relationship": "one_to_n",
"field_type": "TBD",
"prompt": "TBD"
"field_type": "code_primary_breakout",
"prompt": "Return a list of any National Drug Code numbers present. Look for an 11-digit number of the format XXXXX-XXXX-XX."
},
{
"field_name": "LINE_NDC_DESC",
@@ -440,10 +440,10 @@
"prompt": "TBD"
},
{
"field_name": "CLAIM_ADMIT_TYPE",
"field_name": "CLAIM_ADMIT_TYPE_CD",
"relationship": "one_to_n",
"field_type": "TBD",
"prompt": "TBD"
"field_type": "code_primary_breakout",
"prompt": "Identify admit type codes in the text: - Single digit numeric codes (1-9) - Used to indicate hospital admission type"
},
{
"field_name": "AUTH_ADMIT_TYPE_DESC",
@@ -13,6 +13,8 @@ from src.utils.string_utils import extract_text_from_delimiters
import json
import importlib
PIPE_FORMAT_INSTRUCTIONS = "Feel free to justify your answer, but enclose your final answer in |pipes|. If the question cannot be answered with the given context, return |N/A|."
class Field:
def __init__(self, field_dict):
# Base Attributes
@@ -340,7 +342,24 @@ Use the text in the methodology to populate a JSON dictionary with the following
Write your JSON dictionary below:
"""
PIPE_FORMAT_INSTRUCTIONS = "Feel free to justify your answer, but enclose your final answer in |pipes|. If the question cannot be answered with the given context, return |N/A|."
def CODE_PRIMARY_BREAKOUT(context, questions):
return f"""Analyze a given medical service, found in a Payer-Provider contract:
Use the text in the Service to populate a JSON dictionary with the following fields:
{questions}.
For each field, return a list of all codes seen for that field.
For the CPT4_PROC_CD and CPT4_PROC_MOD fields, ensure that each item in each list corresponds with each other.
If any of the codes are not found, do not write a list for that field. Simply populate the field with 'N/A'.
Here is the Service to analyze:
{context}
Write the JSON dictionary below:
"""
def ONE_TO_ONE_SINGLE_FIELD_TEMPLATE(context, question):
return f"""The following is a contract (or excerpt thereof). Answer the following question: {question}