prompt changes

This commit is contained in:
ppanchigar
2026-02-02 16:25:45 -06:00
parent 791558808a
commit 5d1024e9dc
+160 -106
View File
@@ -5,8 +5,32 @@ from src.prompts.fieldset import FieldSet
from src.constants.constants import Constants
from src.utils import string_utils
# Legacy pipe format instructions (deprecated - use JSON formats instead)
PIPE_FORMAT_INSTRUCTIONS = "Briefly explain your answer, then enclose your final answer in |pipes|. If the requested information doesn't apply to this context, return |N/A|. If the information should exist but cannot be clearly identified, return |UNKNOWN|."
# JSON format instructions for standardized LLM outputs
JSON_DICT_FORMAT_INSTRUCTIONS = """Return your final answer as a valid JSON dictionary with the specified field names as keys.
- Use "N/A" for fields where the requested information doesn't apply to this context.
- Use "UNKNOWN" for fields where the information should exist but cannot be clearly identified.
- Ensure the JSON is properly formatted with double quotes around keys and string values."""
JSON_LIST_FORMAT_INSTRUCTIONS = """Return your final answer as a valid JSON list (array).
- If multiple values are found, include all of them as separate items in the list.
- If no values are found, return ["N/A"].
- Ensure the JSON is properly formatted with square brackets and double quotes around string values."""
JSON_DICT_WITH_LISTS_FORMAT_INSTRUCTIONS = """Return your final answer as a valid JSON dictionary where values can be lists (arrays).
- Use lists for fields that may contain multiple values.
- Use "N/A" for fields where the requested information doesn't apply.
- Use "UNKNOWN" for fields where the information should exist but cannot be clearly identified.
- Ensure the JSON is properly formatted with double quotes around keys and string values."""
JSON_LIST_OF_DICTS_FORMAT_INSTRUCTIONS = """Return your final answer as a valid JSON list (array) of dictionaries.
- Each item in the list should be a dictionary with the specified field names as keys.
- If multiple items are found, include all of them as separate dictionaries in the list.
- Use "N/A" for fields within each dictionary where the information doesn't apply.
- Ensure the JSON is properly formatted with square brackets, curly braces, and double quotes."""
# Module-level cached Constants instance for instruction functions
# This is lazily initialized on first use and reused across all instruction calls
_cached_constants = None
@@ -190,20 +214,18 @@ def EXHIBIT_LEVEL_INSTRUCTION() -> str:
"""Static instruction for EXHIBIT_LEVEL prompt caching.
Contains all formatting rules and general instructions.
"""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Extract attributes from a section of a contract.
[FORMATTING INSTRUCTIONS AND DESIRED OUTPUT]
Return a JSON dictionary with the following attributes. It is possible that the page will not have some of the attributes. When this is the case, return N/A.
[GENERAL INSTRUCTIONS]
- For each field, return ALL correct answers found. There may be more than one correct answer. If there are multiple, return them in a pipe-separated list ("|").
- For each field, return ALL correct answers found. There may be more than one correct answer. If there are multiple, return them as a JSON list within the dictionary value (e.g., "field_name": ["value1", "value2"]).
- If a list of valid values is provided, ONLY answer with the EXACT value from that list.
- If there are no correct answers for a given field, write 'N/A' as the answer for that field.
- Be consistent and deterministic; avoid creative paraphrasing.
[OUTPUT FORMAT]
Briefly explain your answer, then put the final answer in the properly-formatted JSON dictionary."""
Briefly explain your answer, then put the final answer in the properly-formatted JSON dictionary.
{JSON_DICT_WITH_LISTS_FORMAT_INSTRUCTIONS}"""
def EXHIBIT_LEVEL(context, fields):
@@ -223,17 +245,18 @@ def DYNAMIC_PRIMARY_TEXT_INSTRUCTION() -> str:
"""Static instruction for DYNAMIC_PRIMARY_TEXT prompt caching.
Contains extraction rules for text-based fields (allows obvious assumptions).
"""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Extract attribute values for dynamic fields from contract text, paying close attention to detail.
[GENERAL INSTRUCTIONS]
- Return all valid, explicitly stated values. If multiple values are found, list them separated by commas.
- If none of the valid values appear explicitly in the text, return N/A.
- Return all valid, explicitly stated values. If multiple values are found, include all of them as separate items in the JSON list.
- If none of the valid values appear explicitly in the text, return ["N/A"].
- Make appropriate and obvious assumptions, but don't take huge leaps of logic.
- For example, you can assume that "Children's Health Insurance Program Perinate (CHIP-P)" is equivalent to "CHIP Perinate", but do not assume that "Children's Health Insurance Program Perinate (CHIP-P)" is equivalent to "Medicaid".
[OUTPUT FORMAT]
Briefly explain your answer before putting the final answer in |pipes|."""
Briefly explain your answer before putting the final answer in a properly-formatted JSON list.
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def DYNAMIC_PRIMARY_TEXT(context, field_name, field_prompt):
@@ -250,11 +273,12 @@ Here is the text to analyze:
def DYNAMIC_PRIMARY_INSTRUCTION() -> str:
"""Legacy instruction for backward compatibility.
Use DYNAMIC_PRIMARY_HEADER_INSTRUCTION or DYNAMIC_PRIMARY_TEXT_INSTRUCTION instead.
Use DYNAMIC_PRIMARY_TEXT_INSTRUCTION instead.
DEPRECATED: This function is maintained for backward compatibility only.
"""
return (
"[OBJECTIVE]\n"
"Extract attribute values for dynamic fields from contract text. Use exact values and return in pipes where instructed."
"Extract attribute values for dynamic fields from contract text. Use exact values and follow output format instructions."
)
@@ -262,7 +286,7 @@ def REIMB_DATES_ASSIGNMENT_INSTRUCTION() -> str:
"""Static instruction for REIMB_DATES_ASSIGNMENT prompt caching.
Contains all date assignment rules and examples.
"""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Identify which date range applies to a specific Reimbursement Term.
You will be shown a Reimbursement Term and the section of a contract from which that term was extracted.
Your task is to determine which date range applies to THIS SPECIFIC reimbursement term.
@@ -322,9 +346,10 @@ First, identify:
2. What date range introduces or applies to that specific section/table?
3. Are there other date ranges in different sections? (These should NOT be assigned to this term)
Then, return a properly-formatted JSON object where the key is "REIMB_DATES" and the value is the correct date range for THIS SPECIFIC term.
Then, return a properly-formatted JSON dictionary where the key is "REIMB_DATES" and the value is the correct date range for THIS SPECIFIC term.
Return ONLY the single date range that applies to this term. Do NOT return multiple date ranges separated by commas.
If there is no date range for this term, return "N/A"."""
If there is no date range for this term, return "N/A".
{JSON_DICT_FORMAT_INSTRUCTIONS}"""
def REIMB_DATES_ASSIGNMENT(
@@ -353,15 +378,16 @@ Reimbursement Term: "{reimb_term}" """
def DYNAMIC_ASSIGNMENT_INSTRUCTION() -> str:
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Identify which field value is associated with a given Reimbursement Term.
[INSTRUCTIONS]
You will be shown a Reimbursement Term, and the section of a contract from which that Reimbursement Term was pulled from.
Closely examine the contract text, find the Reimbursement Term, and decide which field value or values apply to the Reimbursement Term.
If there are multiple values, return them as a list (array) in the JSON dictionary value.
CRITICAL CONSIDERATIONS:
1. EXHIBIT HEADER CONTEXT - Pay close attention to exhibit headers (e.g., "MEDICARE PRODUCT ATTACHMENT") that appear at the beginning of the exhibit section. These headers indicate the scope and context for ALL reimbursement terms within that exhibit. If an exhibit header clearly specifies a line of business (e.g., "MEDICARE PRODUCT ATTACHMENT"), assign values consistent with that header (e.g., "Medicare" for LOB) for all terms in that exhibit. The exhibit header value should be ADDITIVE - it should be included as one of multiple values when other sources (service term, reimbursement term, or subsection context) also provide relevant values. For example, if the exhibit header indicates "Medicare" and the service term or subsection context indicates "Duals", the final assignment should be "Medicare|Duals" (combining both values). The exhibit header value is always included and does not override other valid values.
1. EXHIBIT HEADER CONTEXT - Pay close attention to exhibit headers (e.g., "MEDICARE PRODUCT ATTACHMENT") that appear at the beginning of the exhibit section. These headers indicate the scope and context for ALL reimbursement terms within that exhibit. If an exhibit header clearly specifies a line of business (e.g., "MEDICARE PRODUCT ATTACHMENT"), assign values consistent with that header (e.g., "Medicare" for LOB) for all terms in that exhibit. The exhibit header value should be ADDITIVE - it should be included as one of multiple values when other sources (service term, reimbursement term, or subsection context) also provide relevant values. For example, if the exhibit header indicates "Medicare" and the service term or subsection context indicates "Duals", the final assignment should be ["Medicare", "Duals"] (combining both values in a JSON list). The exhibit header value is always included and does not override other valid values.
2. SUBSECTION CONTEXT - Examine the exhibit text for the subsection header, introductory paragraph, or section introduction that is CLOSEST to the reimbursement term.
@@ -381,14 +407,14 @@ CRITICAL CONSIDERATIONS:
Section markers (numbered items like "1.", "2.", "3.", "4.") create hard boundaries. Example: If "4. Allowable Charges...for any Medicare inpatient admission" appears before "Table 2", you MUST use ONLY context from section 4. Completely ignore subsection context from earlier sections (like "For Covered Services rendered to Covered Person who are eligible for Medicare and enrolled in a Medicare Plan that may include coverage for both Medicare and Medicaid") even if that earlier text mentioned "Table 2" - the section 4 marker invalidates all earlier context.
When a relevant subsection context is found WITHIN THE SAME structural boundary with extremely clear wording about eligibility or program coverage, it should:
- ADD to the exhibit header value (e.g., exhibit header "Medicare" + subsection "both Medicare and Medicaid" = "Medicare|Duals")
- OVERRIDE conflicting information in the service term or reimbursement term (e.g., if subsection says "Duals" but service term says "Medicaid only", assign "Duals" based on subsection)
- ADD to the exhibit header value (e.g., exhibit header "Medicare" + subsection "both Medicare and Medicaid" = ["Medicare", "Duals"])
- OVERRIDE conflicting information in the service term or reimbursement term (e.g., if subsection says "Duals" but service term says "Medicaid only", assign ["Duals"] based on subsection)
3. REIMBURSEMENT TERM CONTEXT - Examine the Reimbursement Term itself for context about what value should be assigned to the field. This is a broad instruction to consider the reimbursement term as a primary source of information. However, if the exhibit header (instruction #1) and nearest subsection context (instruction #2) provide clear answers, the reimbursement term context takes LEAST precedence. The reimbursement term context should be considered in addition to the context provided by the exhibit header and subsection context, but should not override them when they are clear and explicit.
4. Look for what field the Service actually *applies to*. This is not the same as the Schedule used as a basis for calculation. For example, many LOBs use Medicaid or Medicare as a basis for their calculation. The presence of 'Medicaid' or 'Medicare' as a rate does not on it's own guarantee that the Reimbursement Term is 'Medicaid' or 'Medicare'.
5. DUALS VALUE FORMATTING: If the answer appears to be "Medicare|Duals" or "Medicaid|Duals", do NOT simplify to just "Duals" - the pipe-delimited format adds important context. Only simplify to "Duals" alone when it is obvious that Duals alone is sufficient and no additional context is needed.
5. DUALS VALUE FORMATTING: If the answer appears to be a combination like Medicare with Duals or Medicaid with Duals, return them as a JSON list with both values (e.g., ["Medicare", "Duals"] or ["Medicaid", "Duals"]) - including both values adds important context. Only return ["Duals"] alone when it is obvious that Duals alone is sufficient and no additional context is needed.
[PROGRAM FIELD SPECIFIC INSTRUCTIONS - Instructions 6-9 below are PRIMARILY for PROGRAM field assignment, though they may loosely apply to other fields. For LOB field assignment, prioritize instructions 1-5 above these instructions.]
@@ -401,7 +427,12 @@ CRITICAL CONSIDERATIONS:
9. "ALL PROGRAMS" AMBIGUITY - CRITICAL: If you see phrases like "for all Health Plan products & programs" in a table or section, this phrase means "all programs in THIS SECTION", NOT "all programs in the entire document".
- If the table appears AFTER a section that says "STAR, CHIP HMO, CHIP PERINATE, and STAR+PLUS" and BEFORE a section that says "Medicare Advantage", the table applies ONLY to the Medicaid programs (STAR, CHIP, CHIPP, STAR+PLUS) mentioned in that section.
- If the table appears AFTER a section that says "Medicare Advantage", the table applies ONLY to the Medicare programs mentioned in that section.
- NEVER assign programs from separate sections just because you see "all programs" - always determine which section the reimbursement term belongs to based on its position in the document."""
- NEVER assign programs from separate sections just because you see "all programs" - always determine which section the reimbursement term belongs to based on its position in the document.
[OUTPUT FORMAT]
Briefly explain your answer, then return a properly-formatted JSON dictionary where the key is the field name and the value is the answer.
If there are multiple correct answers, return them as a list (array) within the dictionary value.
{JSON_DICT_WITH_LISTS_FORMAT_INSTRUCTIONS}"""
def DYNAMIC_ASSIGNMENT(
@@ -429,11 +460,7 @@ Reimbursement Term: "{reimb_term}"
[{field_name} INFORMATION]
Here is the definition and valid values. Use this information to help you find the right answer.
{field_name} : {field_prompt}
[OUTPUT FORMAT]
Briefly explain your answer, return a properly-formatted JSON object where the key is the field name `{field_name}` and the value is the correct answer. If there is more than one correct answer, return them in a comma-separated list. If there is no correct answer, return 'N/A'
"""
{field_name} : {field_prompt}"""
def REIMBURSEMENT_PRIMARY(context):
@@ -491,7 +518,7 @@ Some types of Reimbursements are special and require additional thought.
def LESSER_OF_DISTRIBUTION_INSTRUCTION() -> str:
return """TASK: Identify "lesser of" or "not to exceed" statements that apply to a service.
return f"""TASK: Identify "lesser of" or "not to exceed" statements that apply to a service.
DEFINITIONS:
"Lesser of" / "not to exceed" = overarching payment rules specifying payment at the lesser of multiple values or capped amounts.
@@ -536,24 +563,26 @@ DECISION LOGIC:
- Join multiple terms: "lesser of X, Y, or Z"
OUTPUT FORMAT:
|[SERVICE] paid at [combined statement]|
Return a JSON list with a single string containing the combined statement.
Examples:
- |Lab Test paid at lesser of $100, billed charges, or 110% Medicare|
- |Radiology paid at $250 or charges|
- |N/A|
- ["Lab Test paid at lesser of $100, billed charges, or 110% Medicare"]
- ["Radiology paid at $250 or charges"]
- ["N/A"]
Example — Intra-exhibit statement references another exhibit → N/A:
- METHODOLOGY: "per visit basis at payment rates established in Attachment A"
- CROSS-EXHIBIT TEMPLATES: None
- EXHIBIT TEXT contains: "lesser of payment rates established in Attachment A or 100% of Medicare"
- Analysis: The only lesser-of statement found references "Attachment A" → IGNORE IT
- Result: |N/A| (no applicable statements remain)
- Result: ["N/A"] (no applicable statements remain)
RETURN N/A WHEN:
RETURN ["N/A"] WHEN:
- No applicable lesser-of statements found
- All statements found reference other exhibits by name (and no cross-exhibit templates provided)
- Statements found but scoped to different service types"""
- Statements found but scoped to different service types
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def LESSER_OF_DISTRIBUTION(
@@ -593,12 +622,12 @@ EXHIBIT TEXT:
---
Analyze the inputs above. Briefly explain your reasoning, then provide your final answer in pipes.
Analyze the inputs above. Briefly explain your reasoning, then provide your final answer as a JSON list.
"""
def LESSER_OF_CHECK_INSTRUCTION() -> str:
return """Classify lesser-of payment statements from healthcare contracts.
return f"""Classify lesser-of payment statements from healthcare contracts.
**IMPORTANT: Check BOTH Service AND Reimbursement fields for exhibit references.**
@@ -666,7 +695,18 @@ Reimbursement: "lesser of Allowable Charges or Company's fee schedule in effect
- GLOBAL is rare. Most contracts will have STANDALONE or EXHIBIT_SPECIFIC entries.
- The presence of "all services" or "covered services" does NOT automatically mean GLOBAL.
- GLOBAL must be a constraint that governs OTHER rates across the contract, not a rate itself.
- When in doubt between STANDALONE and GLOBAL, ask: "Is this a rate, or a rule about rates?" If it's a rate, choose STANDALONE."""
- When in doubt between STANDALONE and GLOBAL, ask: "Is this a rate, or a rule about rates?" If it's a rate, choose STANDALONE.
**OUTPUT FORMAT:**
Briefly explain your reasoning, then return a properly-formatted JSON dictionary with the following structure:
{
"service_term": "<service term>",
"reimb_term": "<reimbursement term>",
"scope": "<one of: GLOBAL, EXHIBIT_SPECIFIC, STANDALONE>",
"target_exhibit": "<one of: ALL, CURRENT, OTHER, or null>",
"exhibit_reference": "<exhibit name if OTHER, else null>"
}
{JSON_DICT_WITH_LISTS_FORMAT_INSTRUCTIONS}"""
def LESSER_OF_CHECK(service_term: str, reimb_term: str, exhibit_title: str):
@@ -676,25 +716,14 @@ def LESSER_OF_CHECK(service_term: str, reimb_term: str, exhibit_title: str):
"""
return f"""**Current Exhibit:** {exhibit_title}
**Service:** {service_term}
**Reimbursement:** {reimb_term}
**Output JSON in |pipes|:**
{{
"service_term": "{service_term}",
"reimb_term": "{reimb_term}",
"scope": "GLOBAL" | "EXHIBIT_SPECIFIC" | "STANDALONE",
"target_exhibit": "ALL" | "CURRENT" | "OTHER" | null,
"exhibit_reference": "<exhibit name if OTHER, else null>"
}}
Briefly explain, then return JSON in |pipes|."""
**Reimbursement:** {reimb_term}"""
def EXHIBIT_TITLE_MATCH_INSTRUCTION() -> str:
"""Static instruction for EXHIBIT_TITLE_MATCH prompt caching.
Contains all matching rules and examples.
"""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Determine if two exhibit references refer to the same exhibit.
[MATCHING RULES]
@@ -706,7 +735,9 @@ Consider the following when matching:
- Different services: "Inpatient Services" does NOT match "Outpatient Services"
[OUTPUT FORMAT]
Briefly explain your reasoning, then return ONLY "YES" or "NO" in |pipes|."""
Briefly explain your reasoning, then return ONLY "YES" or "NO" as a single item in a JSON list.
Examples: ["YES"] or ["NO"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def EXHIBIT_TITLE_MATCH(current_exhibit_title: str, target_exhibit_reference: str):
@@ -1015,18 +1046,19 @@ Methodology: {methodology.replace('"', "'")}"""
def CODE_CATEGORY_INSTRUCTION() -> str:
"""Static instruction for CODE_CATEGORY prompt caching."""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Match a medical Service Term to its corresponding Procedure Code description based on code categories.
[INSTRUCTIONS]
1. Determine if the descriptions are needed. If the Service Term mentions the Code Category (a single-character e.g. A, B, C, ...), without any additional subcategories or descriptors, then there is no need to reference the descriptions. For example, if the Service Term is "A-Codes", the answer is "A0000-A9999". This represents the full range of A-Codes.
1. Determine if the descriptions are needed. If the Service Term mentions the Code Category (a single-character e.g. A, B, C, ...), without any additional subcategories or descriptors, then there is no need to reference the descriptions. For example, if the Service Term is "A-Codes", the answer is ["A0000-A9999"]. This represents the full range of A-Codes.
2. If there are additional subcategories or descriptors accompanying the code category, match them to the closest item or items from the VALID DESCRIPTIONS.
- There can be multiple correct answers. When this is the case, return them all in a list. This may be phrased like "Service1/Service2" or "Service1 and Service2", in which case both Services must be considered.
- There may be no correct answers. When this is the case, return the full range of codes in that category (e.g. A0000-A9999, etc.)
- There can be multiple correct answers. When this is the case, return them all as separate items in the JSON list. This may be phrased like "Service1/Service2" or "Service1 and Service2", in which case both Services must be considered.
- There may be no correct answers. When this is the case, return the full range of codes in that category as a single item in the list (e.g. ["A0000-A9999"], etc.)
[OUTPUT FORMAT]
Explain your answer in 1-2 sentences. Write your final answer in JSON list format."""
Explain your answer in 1-2 sentences. Write your final answer in a properly-formatted JSON list.
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def CODE_CATEGORY(service, choices):
@@ -1042,7 +1074,7 @@ Here is the Service Term to analyze:
def CODE_IMPLICIT_SPECIAL_INSTRUCTION() -> str:
"""Static instruction for CODE_IMPLICIT_SPECIAL prompt caching."""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Classify a medical Service Term into special predefined categories for implicit code mapping.
[INSTRUCTIONS]
@@ -1054,7 +1086,9 @@ Classify a medical Service Term into special predefined categories for implicit
- If none of the above cases apply, respond "N/A". If any of the above are mentioned but only in the context of being excluded from the service, respond "N/A".
[OUTPUT FORMAT]
Briefly explain your answer, but put your final answer in |pipes|"""
Briefly explain your answer, then put your final answer as a single item in a JSON list.
Examples: ["Drugs"], ["Vaccines"], ["PT/OT/ST"], ["PT"], ["Surgery"], ["N/A"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def CODE_IMPLICIT_SPECIAL(service):
@@ -1066,7 +1100,7 @@ Here is the Service to analyze:
def CODE_IMPLICIT_INSTRUCTION() -> str:
"""Static instruction for CODE_IMPLICIT prompt caching."""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Match a medical Service Term to its corresponding Procedure Code description using implicit matching logic.
[INSTRUCTIONS]
@@ -1080,11 +1114,12 @@ Match a medical Service Term to its corresponding Procedure Code description usi
- IGNORE distracting terms like "Services" or "Procedures" in both the Service and the Description. They are meaningless for the purpose of this exercise.
- For each Description in VALID DESCRIPTIONS, ask yourself the following question: Is the Description SYNONYMOUS with the Service?
- **Note**: Do NOT simply categorize the Service into the Description that it falls under. You are looking specifically for synonymous Service-Description matches. For example, "Nutritional Evaluations" is not synonymous with "Evaluations", because not ALL "Evaluations" are "Nutritional Evaluations".
- There can be multiple correct answers. When this is the case, return them all in a list.
- There may be no correct answers, especially when the Service is much more specific than any of the descriptions. When this is the case, simply return an empty list "[]".
- There can be multiple correct answers. When this is the case, return them all as separate items in the JSON list.
- There may be no correct answers, especially when the Service is much more specific than any of the descriptions. When this is the case, simply return an empty list [].
[OUTPUT FORMAT]
Explain your answer, ensuring each point in the instructions is addressed. Then return your final answer in JSON list format."""
Explain your answer, ensuring each point in the instructions is addressed. Then return your final answer in a properly-formatted JSON list.
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def CODE_IMPLICIT(service, choices):
@@ -1100,7 +1135,7 @@ Here is the Service Term to analyze:
def CODE_LAST_CHECK_INSTRUCTION() -> str:
"""Static instruction for CODE_LAST_CHECK prompt caching."""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Analyze a given healthcare-related term to determine if it represents a specific medical service.
[CLASSIFICATION RULES]
@@ -1112,7 +1147,9 @@ Analyze a given healthcare-related term to determine if it represents a specific
- A nonsensical or non-service phrase
[OUTPUT FORMAT]
Briefly explain your answer, then put your final answer in |pipes|."""
Briefly explain your answer, then put your final answer as a single item in a JSON list.
Examples: ["Specific"] or ["Generic"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def CODE_LAST_CHECK(service):
@@ -1123,7 +1160,7 @@ def CODE_LAST_CHECK(service):
def FILL_BILL_TYPE_INSTRUCTION() -> str:
"""Static instruction for FILL_BILL_TYPE prompt caching."""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Analyze a given medical Service Term to determine which Bill Type Code Description it falls under.
[INSTRUCTIONS]
@@ -1137,7 +1174,8 @@ Analyze a given medical Service Term to determine which Bill Type Code Descripti
- "dialysis" --> ["Dialysis Center"]
[OUTPUT FORMAT]
Briefly explain your answer, then return your final answer in JSON list format."""
Briefly explain your answer, then return your final answer in a properly-formatted JSON list.
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def FILL_BILL_TYPE(service, choices, reimb_term=None, exhibit_text=None):
@@ -1189,7 +1227,7 @@ Briefly explain your answer, then put the final answer in a properly-formatted J
def ONE_TO_ONE_SINGLE_FIELD_INSTRUCTION() -> str:
return (
"[OBJECTIVE]\n"
"Answer a single, deterministic question about the contract text. Return result in pipes as instructed."
"Answer a single, deterministic question about the contract text. Return result in JSON dictionary format as instructed."
)
@@ -1201,11 +1239,12 @@ IMPORTANT DISTINCTION:
- Providers: Physicians, physician groups, hospitals, clinics who DELIVER healthcare
- Payers: Insurance companies, health plans who PAY for healthcare services
CRITICAL: If a provider has multiple TINs or NPIs, include ALL of them separated by pipes (|) in the same provider record. Do NOT create separate records for the same provider entity.
CRITICAL: If a provider has multiple TINs or NPIs, include ALL of them as a JSON list in the same provider record. Do NOT create separate records for the same provider entity.
Examples:
- If you see "NPI: 1083087266 and 1396117412", return "NPI": "1083087266|1396117412"
- If you see "Tax ID: 12-3456789, also 98-7654321", return "TIN": "123456789|987654321"
- If you see "NPI: 1083087266 and 1396117412", return "NPI": ["1083087266", "1396117412"]
- If you see "Tax ID: 12-3456789, also 98-7654321", return "TIN": ["123456789", "987654321"]
- If there is only one TIN or NPI, still return it as a string (not a list): "TIN": "123456789"
Briefly explain your reasoning. After your explanation, include the heading "FINAL PROVIDER INFO:" followed by a properly formatted JSON array with your final output.
@@ -1275,9 +1314,9 @@ def FULL_CONTEXT_CLAIM_TYPES_ADDITIONAL_INSTRUCTION():
def FULL_CONTEXT_ADDITIONAL_INSTRUCTIONS(allow_na):
if allow_na:
return " Only provide an answer if that answer clearly applies to the ENTIRE contract. Otherwise, answer N/A. If there are multiple correct answers, return them in a pipe (|) separated list."
return " Only provide an answer if that answer clearly applies to the ENTIRE contract. Otherwise, answer N/A. If there are multiple correct answers, return them as a JSON list (array) in the dictionary value."
else:
return " Do NOT leave this field N/A. Choose the most appropriate answer based on the context. If there are multiple answers, return them in a pipe (|) separated list."
return " Do NOT leave this field N/A. Choose the most appropriate answer based on the context. If there are multiple answers, return them as a JSON list (array) in the dictionary value."
def FULL_CONTEXT_PAYER_NAME_ADDITIONAL_INSTRUCTION():
@@ -1307,12 +1346,12 @@ def CHECK_PROVIDER_NAME_MATCH_INSTRUCTION() -> str:
"""Static instruction for CHECK_PROVIDER_NAME_MATCH prompt caching.
Contains all matching rules and critical exclusions.
"""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Determine if two provider names refer to the same healthcare organization.
[MATCHING RULES]
1. PROVIDER NAME A must appear in PROVIDER NAME B (either as an exact match or close variation).
2. If PROVIDER NAME B contains multiple names (separated by ' | '), check each name individually.
2. If PROVIDER NAME B contains multiple names (which may appear separated by delimiters in the input), check each name individually.
3. Legal entity suffixes (LLC, Inc, PA, PC, etc.) can be ignored when matching.
4. D/B/A / "doing business as" variations count as matches (e.g., "Lakeview Hospital" matches "Hospital Corporation of Utah d.b.a. Lakeview Hospital").
5. Acronyms that clearly represent the same entity count as matches (e.g., "MHS" matches "Memorial Hospital System").
@@ -1324,7 +1363,9 @@ Determine if two provider names refer to the same healthcare organization.
- Corporate umbrella names unless they are explicitly listed in PROVIDER NAME B.
[OUTPUT FORMAT]
Briefly explain your reasoning. Then return ONLY 'Y' (match found) or 'N' (no match found). Enclose your final answer in |pipes|."""
Briefly explain your reasoning. Then return ONLY 'Y' (match found) or 'N' (no match found) as a single item in a JSON list.
Examples: ["Y"] or ["N"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def CHECK_PROVIDER_NAME_MATCH_PROMPT(
@@ -1337,7 +1378,7 @@ def CHECK_PROVIDER_NAME_MATCH_PROMPT(
PROVIDER NAME A: {provider_name}
PROVIDER NAME B: {hybrid_smart_chunking_provider_group_name}
Note: PROVIDER NAME B is typically a single name but may contain multiple names separated by ' | '. Determine if PROVIDER NAME A matches PROVIDER NAME B (or ANY name if multiple are present)."""
Note: PROVIDER NAME B is typically a single name but may contain multiple names. Determine if PROVIDER NAME A matches PROVIDER NAME B (or ANY name if multiple are present)."""
def ONE_TO_ONE_MULTI_FIELD_TEMPLATE(context, questions: dict[str, str]):
@@ -1410,7 +1451,7 @@ def EXHIBIT_HEADER_INSTRUCTION() -> str:
EXHIBIT_HEADER_MARKERS = constants.EXHIBIT_HEADER_MARKERS
markers_text = "\n* ".join(EXHIBIT_HEADER_MARKERS)
return f"""[OBJECTIVE]
Analyze contract excerpts and extract the full exhibit/attachment header found.
Capture the complete hierarchy of document identifiers present in the text.
@@ -1437,9 +1478,11 @@ The following keywords and phrases should be considered as exhibit/attachment he
* DO NOT include unrelated text written in lowercase or title case.
[OUTPUT FORMAT]
If there is no Exhibit Header present, return |N/A|.
Enclose your final answer in |pipes|, followed by a brief explanation.
Before returning any output, ensure that all instructions for inclusion were followed."""
If there is no Exhibit Header present, return ["N/A"].
Return your final answer as a single item in a JSON list, followed by a brief explanation.
Before returning any output, ensure that all instructions for inclusion were followed.
Example: ["Exhibit A: Commercial Services"] or ["Attachment B - Provider Compensation Schedule"] or ["N/A"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def EXHIBIT_HEADER(context):
@@ -1456,7 +1499,7 @@ def EXHIBIT_LINKAGE_INSTRUCTION() -> str:
"""Static instruction for EXHIBIT_LINKAGE prompt caching.
Contains all decision rules for determining meaningful differences.
"""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Determine if two exhibit headers are meaningfully different from each other.
[DECISION RULES]
@@ -1467,8 +1510,10 @@ Determine if two exhibit headers are meaningfully different from each other.
* If Header 1 directly references Header 2 in a way that links the two, then they are NOT meaningfully different. This linkage also applies if Header 2 references Header 1.
[OUTPUT FORMAT]
Return |Y| if the two Headers are meaningfully different. Return |N| if they are not.
Briefly explain your answer, then enclose your final answer in |pipes|."""
Return ["Y"] if the two Headers are meaningfully different. Return ["N"] if they are not.
Briefly explain your answer, then return your final answer as a single item in a JSON list.
Examples: ["Y"] or ["N"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def EXHIBIT_LINKAGE(header1, header2):
@@ -1550,7 +1595,12 @@ Return NO if EITHER term contains (even if valid payment method exists):
- Non-reimbursement statements: "not covered", "not payable", "excluded", "shall not bill", "shall not collect"
- Chargemaster/CDM references
"""
---
[OUTPUT FORMAT]
Briefly explain your reasoning following the three conditions above, then return your final answer as a single item in a JSON list.
Examples: ["YES"] or ["NO"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def VALIDATE_REIMBURSEMENTS_PROMPT(service_term: str, reimb_term: str) -> str:
"""Returns ONLY dynamic content for validation.
@@ -1567,9 +1617,8 @@ REIMBURSEMENT TERM: {reimb_term}
2. Is REIMBURSEMENT TERM a specific payment method?
3. Any disqualifiers in either term?
If 1=yes, 2=yes, 3=no → return |YES|
Otherwise → return |NO|
Briefly explain your reasoning, then return YES or NO in |pipes|"""
If 1=yes, 2=yes, 3=no → return ["YES"]
Otherwise → return ["NO"]"""
def DATE_FIX_INSTRUCTION() -> str:
@@ -1588,32 +1637,32 @@ Output: Date in YYYY/MM/DD format, or input if it's a duration, or "N/A" if ambi
4. Return N/A if: missing/ambiguous month or year components, or invalid dates. If just the day is missing, assume it's the first of the month.
5. For ambiguous input cases, assume American format (MM/DD/YYYY) and apply YYYY/MM/DD formatting
6. Any day values with spaces or leading zeros (e.g., '0 1' or '01') are interpreted as single-digit days
7. Return final answer in |pipes|
7. Return final answer as a single item in a JSON list
[EXAMPLES]
Input: "7th day of February, 2002"
Output: |2002/02/07|
Output: ["2002/02/07"]
Input: "Sep 20, 2022"
Output: |2022/09/20|
Output: ["2022/09/20"]
Input: "3 years"
Output: |3 years|
Output: ["3 years"]
Input: "FEB 0 1 2020"
Output: |2020/02/01|
Output: ["2020/02/01"]
Input: "8.1.10" # (assumed MM.DD.YYYY)
Output: |2010/08/01|
Output: ["2010/08/01"]
Input: "March 2014" # (missing day, assume 1st)
Output: |2014/03/01|
Output: ["2014/03/01"]
Input: "Feb 26, 2_0_" # (incomplete year)
Output: |N/A|
Output: ["N/A"]
[OUTPUT FORMAT]
{PIPE_FORMAT_INSTRUCTIONS}"""
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def DATE_FIX_PROMPT(context: str) -> str:
@@ -1651,7 +1700,7 @@ def CARVEOUT_CHECK_INSTRUCTION() -> str:
special_case_text = "\n\n".join(
[f"{name} : {desc}" for name, desc in special_case_definitions.items()]
)
return f"""[OBJECTIVE]
Examine the Reimbursement Term and identify which case it falls under.
@@ -1669,7 +1718,9 @@ Special cases: {special_case_text}
- Always return one value from the combined list of cases above; do not return 'N/A' or 'UNKNOWN'.
[OUTPUT FORMAT]
Briefly explain your answer (including why it was one of carveout cases or special cases), then enclose your final answer in |pipes|."""
Briefly explain your answer (including why it was one of carveout cases or special cases), then return your final answer as a single item in a JSON list.
Example: ["OUTLIER_TERM"] or ["RATE_ESCALATOR"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def CARVEOUT_CHECK(service_term: str, reimb_term: str):
@@ -1743,7 +1794,7 @@ def LOB_RELATIONSHIP_INSTRUCTION() -> str:
"""Static instruction for LOB_RELATIONSHIP prompt caching.
Contains background, decision rules, and output format.
"""
return """[OBJECTIVE]
return f"""[OBJECTIVE]
Analyze an exhibit from a Payer-Provider contract to determine if LOB and Program relationship is Inclusive or Exclusive.
[BACKGROUND]
@@ -1762,9 +1813,10 @@ Analyze an exhibit from a Payer-Provider contract to determine if LOB and Progra
[OUTPUT FORMAT - CRITICAL]
You MUST format your response as follows:
1. Briefly explain your reasoning
2. Then put your final answer in pipe delimiters: |Inclusive| or |Exclusive|
Example: "The contract shows... |Inclusive|"
Your response MUST include the pipe delimiters (|) around your final answer."""
2. Then put your final answer as a single item in a JSON list: ["Inclusive"] or ["Exclusive"]
Example: "The contract shows... ["Inclusive"]"
Your response MUST include the JSON list with your final answer.
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def LOB_RELATIONSHIP(exhibit_text, dynamic_primary_values):
@@ -1796,8 +1848,9 @@ Determine the initial termination date of the contract from effective date and t
- Only provide the first termination date, ignoring any automatic or optional renewals.
[OUTPUT FORMAT]
Provide the date in YYYY/MM/DD format only.
{PIPE_FORMAT_INSTRUCTIONS}"""
Provide the date in YYYY/MM/DD format only, as a single item in a JSON list.
Example: ["2024/01/31"] or ["N/A"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def DERIVED_TERM_DATE_PROMPT(
@@ -1829,10 +1882,11 @@ Your job is to determine which special case term (by index number) is most close
[RULES]
- Use context clues from the contract text to match the reimbursement term to the most appropriate special case term
- If multiple special case terms could apply, choose the one with the strongest contextual connection
- Return only the integer index of the matching term
- Return only the integer index of the matching term as a single item in a JSON list
[OUTPUT FORMAT]
{PIPE_FORMAT_INSTRUCTIONS}"""
Example: ["0"] or ["2"] or ["5"]
{JSON_LIST_FORMAT_INSTRUCTIONS}"""
def SPECIAL_CASE_ASSIGNMENT(