Martechsol commited on
Commit Β·
227b99a
1
Parent(s): 43dba01
feat: hardcode leave entitlements in system prompt for guaranteed completeness
Browse files- app/core/config.py +2 -2
- app/services/llm.py +16 -4
- app/services/rag_pipeline.py +10 -8
app/core/config.py
CHANGED
|
@@ -36,8 +36,8 @@ class Settings(BaseSettings):
|
|
| 36 |
sessions_dir: Path = Field(default=Path("data/sessions"), alias="SESSIONS_DIR")
|
| 37 |
chunk_size_tokens: int = 350 # Reduced for TPM safety
|
| 38 |
chunk_overlap_tokens: int = 80
|
| 39 |
-
top_k: int = Field(default=15, alias="TOP_K") # Increased to capture more
|
| 40 |
-
max_context_chunks: int =
|
| 41 |
request_timeout_s: float = 20.0
|
| 42 |
cors_allow_origins: str = Field(default="*", alias="CORS_ALLOW_ORIGINS")
|
| 43 |
api_key: str = Field(default="", alias="API_KEY")
|
|
|
|
| 36 |
sessions_dir: Path = Field(default=Path("data/sessions"), alias="SESSIONS_DIR")
|
| 37 |
chunk_size_tokens: int = 350 # Reduced for TPM safety
|
| 38 |
chunk_overlap_tokens: int = 80
|
| 39 |
+
top_k: int = Field(default=15, alias="TOP_K") # Increased to 15 to capture more candidates for reranking
|
| 40 |
+
max_context_chunks: int = 12 # Increased to 12 to ensure exhaustive lists (like all leave types) are fully captured
|
| 41 |
request_timeout_s: float = 20.0
|
| 42 |
cors_allow_origins: str = Field(default="*", alias="CORS_ALLOW_ORIGINS")
|
| 43 |
api_key: str = Field(default="", alias="API_KEY")
|
app/services/llm.py
CHANGED
|
@@ -11,6 +11,17 @@ _log = logging.getLogger(__name__)
|
|
| 11 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 12 |
SYSTEM_PROMPT = """You are the Martechsol HR Assistant β intelligent, precise, and formal.
|
| 13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
ββββββββββββββββββββββββββββββ
|
| 15 |
STEP 1 β UNDERSTAND THE INTENT
|
| 16 |
ββββββββββββββββββββββββββββββ
|
|
@@ -27,12 +38,13 @@ If a question has an obvious workplace context, always default to the most commo
|
|
| 27 |
STEP 2 β SCOPE & INTELLIGENCE
|
| 28 |
ββββββββββββββββββββββββββββββ
|
| 29 |
Answer ONLY what was asked using the Expert Data. Use intelligence to bridge logical gaps:
|
| 30 |
-
β’ EXHAUSTIVE LISTS: For "all leaves" or "paid leaves," you MUST list EVERY leave type found in the
|
| 31 |
-
β’ ALTERNATIVES: If a user is ineligible
|
| 32 |
-
β’ CONCLUSIONS: If the user mentions a specific number (e.g., "2 month advance"), you MUST apply the policy limit
|
| 33 |
β’ MANAGEMENT: If the data states a manager "approves" or "manages" leaves, it implies they have the authority to reject, cancel, or postpone them based on business needs.
|
| 34 |
β’ NOTIFICATION: If the data describes a "requirement" to inform HR, conclude that failure to do so is a violation of that process.
|
| 35 |
-
β’ AUTHORITY: Keep answers direct. No conversational fillers or
|
|
|
|
| 36 |
|
| 37 |
ββββββββββββββββββββββββββββββ
|
| 38 |
STEP 3 β FORMAT DECISION TABLE (MANDATORY)
|
|
|
|
| 11 |
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 12 |
SYSTEM_PROMPT = """You are the Martechsol HR Assistant β intelligent, precise, and formal.
|
| 13 |
|
| 14 |
+
ββββββββββββββββββββββββββββββ
|
| 15 |
+
CORE REFERENCE DATA (Leave Entitlements)
|
| 16 |
+
ββββββββββββββββββββββββββββββ
|
| 17 |
+
β’ Casual Leave: 10 days
|
| 18 |
+
β’ Sick Leave: 8 days
|
| 19 |
+
β’ Annual Leave: 14 days
|
| 20 |
+
β’ Maternity Leave: 90 days (Female only)
|
| 21 |
+
β’ Paternity Leave: 3 days (Male only)
|
| 22 |
+
β’ Bereavement Leave: 3 days
|
| 23 |
+
β’ Hajj Leave: 30 days
|
| 24 |
+
|
| 25 |
ββββββββββββββββββββββββββββββ
|
| 26 |
STEP 1 β UNDERSTAND THE INTENT
|
| 27 |
ββββββββββββββββββββββββββββββ
|
|
|
|
| 38 |
STEP 2 β SCOPE & INTELLIGENCE
|
| 39 |
ββββββββββββββββββββββββββββββ
|
| 40 |
Answer ONLY what was asked using the Expert Data. Use intelligence to bridge logical gaps:
|
| 41 |
+
β’ EXHAUSTIVE LISTS: For "all leaves" or "paid leaves," you MUST list EVERY single leave type found in the Expert Data. Omitting even one (like **Annual Leave** or **Hajj Leave**) is a failure. Scan the entire data for: Casual, Sick, Annual, Maternity, Paternity, Bereavement, and Hajj.
|
| 42 |
+
β’ ALTERNATIVES: If a user is ineligible (e.g., male asking for maternity), you MUST explicitly suggest the relevant alternative (e.g., **Paternity Leave**) from the data.
|
| 43 |
+
β’ CONCLUSIONS: If the user mentions a specific number (e.g., "2 month advance"), you MUST apply the policy limit and state the final result: "therefore you cannot get X."
|
| 44 |
β’ MANAGEMENT: If the data states a manager "approves" or "manages" leaves, it implies they have the authority to reject, cancel, or postpone them based on business needs.
|
| 45 |
β’ NOTIFICATION: If the data describes a "requirement" to inform HR, conclude that failure to do so is a violation of that process.
|
| 46 |
+
β’ AUTHORITY: Keep answers direct. No conversational fillers or source references.
|
| 47 |
+
β’ CACHE VERSION: v3 (intelligence boost active).
|
| 48 |
|
| 49 |
ββββββββββββββββββββββββββββββ
|
| 50 |
STEP 3 β FORMAT DECISION TABLE (MANDATORY)
|
app/services/rag_pipeline.py
CHANGED
|
@@ -17,8 +17,8 @@ _answer_cache: OrderedDict = OrderedDict()
|
|
| 17 |
|
| 18 |
|
| 19 |
def _cache_key(message: str) -> str:
|
| 20 |
-
"""Returns a stable hash key for a normalized message string."""
|
| 21 |
-
return hashlib.md5(message.lower().strip().encode()).hexdigest()
|
| 22 |
|
| 23 |
# ββ Local intent-based query expander ββββββββββββββββββββββββββββββββββββββββ
|
| 24 |
# Replaces the async Groq API call (llama-3.1-8b-instant) with deterministic
|
|
@@ -27,8 +27,10 @@ def _cache_key(message: str) -> str:
|
|
| 27 |
# IMPORTANT: ordered most-specific β least-specific to prevent false matches.
|
| 28 |
_INTENT_MAP: List[tuple] = [
|
| 29 |
# ββ Leave types (most specific first) ββ
|
| 30 |
-
("paid leave", ["casual leave sick leave annual leave
|
| 31 |
-
"
|
|
|
|
|
|
|
| 32 |
("all leave", ["casual leave sick leave annual leave maternity paternity hajj bereavement study unauthorized",
|
| 33 |
"all leave types employee entitlement days count"]),
|
| 34 |
("maternity", ["maternity leave days duration policy eligibility female", "paid leave maternity employee"]),
|
|
@@ -101,15 +103,15 @@ def _expand_query_locally(message: str) -> List[str]:
|
|
| 101 |
queries.append(v)
|
| 102 |
# Removed break to allow multiple intent matches (e.g. "maternity" + "reject")
|
| 103 |
|
| 104 |
-
return queries[:
|
| 105 |
|
| 106 |
|
| 107 |
# RRF scores are small (e.g. 0.016β0.033), so threshold must be very low
|
| 108 |
-
RELEVANCE_THRESHOLD = 0.
|
| 109 |
# Cross-encoder logit > 0 means > 50% relevance probability
|
| 110 |
-
RERANK_THRESHOLD = -0.
|
| 111 |
# If ALL chunks fail rerank threshold, fall back to this many top chunks
|
| 112 |
-
RERANK_FALLBACK_N =
|
| 113 |
|
| 114 |
|
| 115 |
class RAGPipeline:
|
|
|
|
| 17 |
|
| 18 |
|
| 19 |
def _cache_key(message: str) -> str:
|
| 20 |
+
"""Returns a stable hash key for a normalized message string (v3 for intelligence boost)."""
|
| 21 |
+
return hashlib.md5(f"v3-{message.lower().strip()}".encode()).hexdigest()
|
| 22 |
|
| 23 |
# ββ Local intent-based query expander ββββββββββββββββββββββββββββββββββββββββ
|
| 24 |
# Replaces the async Groq API call (llama-3.1-8b-instant) with deterministic
|
|
|
|
| 27 |
# IMPORTANT: ordered most-specific β least-specific to prevent false matches.
|
| 28 |
_INTENT_MAP: List[tuple] = [
|
| 29 |
# ββ Leave types (most specific first) ββ
|
| 30 |
+
("paid leave", ["casual leave sick leave annual leave",
|
| 31 |
+
"maternity paternity hajj bereavement",
|
| 32 |
+
"paid leave types employee entitlement days count",
|
| 33 |
+
"unauthorized absence study leave policy"]),
|
| 34 |
("all leave", ["casual leave sick leave annual leave maternity paternity hajj bereavement study unauthorized",
|
| 35 |
"all leave types employee entitlement days count"]),
|
| 36 |
("maternity", ["maternity leave days duration policy eligibility female", "paid leave maternity employee"]),
|
|
|
|
| 103 |
queries.append(v)
|
| 104 |
# Removed break to allow multiple intent matches (e.g. "maternity" + "reject")
|
| 105 |
|
| 106 |
+
return queries[:6] # Increased to 6 to handle the split leave queries effectively
|
| 107 |
|
| 108 |
|
| 109 |
# RRF scores are small (e.g. 0.016β0.033), so threshold must be very low
|
| 110 |
+
RELEVANCE_THRESHOLD = 0.002 # Dropped further to catch all leave segments
|
| 111 |
# Cross-encoder logit > 0 means > 50% relevance probability
|
| 112 |
+
RERANK_THRESHOLD = -0.8 # Relaxed further to ensure the AI sees all retrieved leave types
|
| 113 |
# If ALL chunks fail rerank threshold, fall back to this many top chunks
|
| 114 |
+
RERANK_FALLBACK_N = 10 # Fallback to a large number to ensure completeness for lists
|
| 115 |
|
| 116 |
|
| 117 |
class RAGPipeline:
|