Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- src/system_prompt.py +30 -1
- src/verify.py +4 -24
src/system_prompt.py
CHANGED
|
@@ -71,6 +71,16 @@ CRITICAL FORMAT RULES:
|
|
| 71 |
- A response that is 2 punchy sentences beats a response that is 8 bullet points of equal weight
|
| 72 |
- Match format to content every single time, not to user's last format request
|
| 73 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
DISCLAIMER — always at end, never at start:
|
| 75 |
"Note: This is not legal advice. Consult a qualified advocate for your specific situation."
|
| 76 |
Never open with disclaimer. It kills the energy."""
|
|
@@ -192,7 +202,18 @@ Should reveal opportunity or flag risk.""",
|
|
| 192 |
"reassurance": """Acknowledge difficulty briefly.
|
| 193 |
Immediately establish that options exist.
|
| 194 |
Give one concrete thing that shows this isn't hopeless.
|
| 195 |
-
Then move forward."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
}
|
| 197 |
|
| 198 |
STAGE_MAP = {
|
|
@@ -332,4 +353,12 @@ Set action_needed to "strategy_synthesis" when user message contains any of:
|
|
| 332 |
"final advice", "wrap up", "conclude", "what have we established", "plan of action"
|
| 333 |
This triggers generation of the full structured strategy document using ALL accumulated case state.
|
| 334 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 335 |
- Output ONLY the JSON. No explanation. No preamble. No markdown fences."""
|
|
|
|
| 71 |
- A response that is 2 punchy sentences beats a response that is 8 bullet points of equal weight
|
| 72 |
- Match format to content every single time, not to user's last format request
|
| 73 |
|
| 74 |
+
RESPONSE LENGTH — match to what was actually asked:
|
| 75 |
+
- "just name X" or "just list X" or "only X" → maximum 10 lines, no explanations
|
| 76 |
+
- Simple factual question → 1-3 sentences
|
| 77 |
+
- Advice request → 1-3 paragraphs maximum
|
| 78 |
+
- Strategy request → structured but still concise
|
| 79 |
+
- Document draft → full document length as needed
|
| 80 |
+
- NEVER write 5 paragraphs when 1 paragraph answers the question
|
| 81 |
+
- If you find yourself writing a 4th paragraph on the same point, stop
|
| 82 |
+
- The user's patience is finite. Respect it.
|
| 83 |
+
|
| 84 |
DISCLAIMER — always at end, never at start:
|
| 85 |
"Note: This is not legal advice. Consult a qualified advocate for your specific situation."
|
| 86 |
Never open with disclaimer. It kills the energy."""
|
|
|
|
| 202 |
"reassurance": """Acknowledge difficulty briefly.
|
| 203 |
Immediately establish that options exist.
|
| 204 |
Give one concrete thing that shows this isn't hopeless.
|
| 205 |
+
Then move forward.""",
|
| 206 |
+
|
| 207 |
+
"document_draft": """User wants an actual document drafted — legal notice, letter, complaint, FIR, agreement, or similar.
|
| 208 |
+
DO NOT analyse or explain. DRAFT THE ACTUAL DOCUMENT.
|
| 209 |
+
Use proper legal document format:
|
| 210 |
+
- Header with FROM, TO, DATE, SUBJECT
|
| 211 |
+
- Body with numbered paragraphs
|
| 212 |
+
- Formal legal language throughout
|
| 213 |
+
- Cite specific sections inline (u/s 378 IPC)
|
| 214 |
+
- Clear demand or statement of facts
|
| 215 |
+
- Closing with signature block
|
| 216 |
+
This must look like a real document a lawyer would send, not a paragraph about what the document should say."""
|
| 217 |
}
|
| 218 |
|
| 219 |
STAGE_MAP = {
|
|
|
|
| 353 |
"final advice", "wrap up", "conclude", "what have we established", "plan of action"
|
| 354 |
This triggers generation of the full structured strategy document using ALL accumulated case state.
|
| 355 |
|
| 356 |
+
DOCUMENT DRAFT — trigger rule:
|
| 357 |
+
Set action_needed to "document_draft" when user message contains any of:
|
| 358 |
+
"draft a letter", "write a letter", "send a letter", "prepare a letter",
|
| 359 |
+
"draft a notice", "legal notice", "write a complaint", "draft an FIR",
|
| 360 |
+
"prepare a document", "official letter", "send him a letter",
|
| 361 |
+
"draft from the side of", "write on behalf of"
|
| 362 |
+
format_decision must be "prose" — documents are continuous formatted text not bullets
|
| 363 |
+
|
| 364 |
- Output ONLY the JSON. No explanation. No preamble. No markdown fences."""
|
src/verify.py
CHANGED
|
@@ -22,7 +22,7 @@ import numpy as np
|
|
| 22 |
logger = logging.getLogger(__name__)
|
| 23 |
|
| 24 |
# ── Similarity threshold ──────────────────────────────────
|
| 25 |
-
SIMILARITY_THRESHOLD = 0.
|
| 26 |
|
| 27 |
|
| 28 |
def _normalise(text: str) -> str:
|
|
@@ -34,35 +34,15 @@ def _normalise(text: str) -> str:
|
|
| 34 |
|
| 35 |
|
| 36 |
def _extract_quotes(text: str) -> list:
|
| 37 |
-
"""Extract quoted phrases
|
| 38 |
quotes = []
|
| 39 |
-
|
| 40 |
-
# Extract explicitly quoted phrases
|
| 41 |
patterns = [
|
| 42 |
-
r'"([^"]{
|
| 43 |
-
r'\u201c([^\u201d]{
|
| 44 |
]
|
| 45 |
for pattern in patterns:
|
| 46 |
found = re.findall(pattern, text)
|
| 47 |
quotes.extend(found)
|
| 48 |
-
|
| 49 |
-
# If no explicit quotes, extract key sentences for verification
|
| 50 |
-
if not quotes:
|
| 51 |
-
sentences = re.split(r'(?<=[.!?])\s+', text)
|
| 52 |
-
# Take sentences that make specific legal claims
|
| 53 |
-
for s in sentences:
|
| 54 |
-
s = s.strip()
|
| 55 |
-
# Sentences with section numbers, case citations, or specific claims
|
| 56 |
-
if (len(s) > 40 and
|
| 57 |
-
any(indicator in s.lower() for indicator in [
|
| 58 |
-
"section", "act ", "ipc", "crpc",
|
| 59 |
-
"article ", "judgment", "punishable",
|
| 60 |
-
"imprisonment", "years rigorous"
|
| 61 |
-
])):
|
| 62 |
-
quotes.append(s)
|
| 63 |
-
if len(quotes) >= 3: # cap at 3 sentences
|
| 64 |
-
break
|
| 65 |
-
|
| 66 |
return quotes
|
| 67 |
|
| 68 |
|
|
|
|
| 22 |
logger = logging.getLogger(__name__)
|
| 23 |
|
| 24 |
# ── Similarity threshold ──────────────────────────────────
|
| 25 |
+
SIMILARITY_THRESHOLD = 0.45 # cosine similarity — tunable
|
| 26 |
|
| 27 |
|
| 28 |
def _normalise(text: str) -> str:
|
|
|
|
| 34 |
|
| 35 |
|
| 36 |
def _extract_quotes(text: str) -> list:
|
| 37 |
+
"""Extract only explicitly quoted phrases from answer."""
|
| 38 |
quotes = []
|
|
|
|
|
|
|
| 39 |
patterns = [
|
| 40 |
+
r'"([^"]{20,})"',
|
| 41 |
+
r'\u201c([^\u201d]{20,})\u201d',
|
| 42 |
]
|
| 43 |
for pattern in patterns:
|
| 44 |
found = re.findall(pattern, text)
|
| 45 |
quotes.extend(found)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
return quotes
|
| 47 |
|
| 48 |
|