Abid Ali Awan Codex commited on
Commit ·
8380712
1
Parent(s): 3918768
Reduce traces to descriptive inputs
Browse filesCo-Authored-By: Codex <codex@openai.com>
- README.md +2 -1
- app.py +0 -3
- tests/test_tracing.py +13 -11
- traces/data/trace_samples.jsonl +6 -6
- traces/dataset_card.md +3 -4
- traces/runtime.py +12 -114
- traces/scripts/seed_trace_dataset.py +0 -3
README.md
CHANGED
|
@@ -128,7 +128,8 @@ turn it off before submitting.
|
|
| 128 |
|
| 129 |
Trace creation is deterministic Python logic and makes no additional model
|
| 130 |
request. It records a safe input type or image description, input category,
|
| 131 |
-
urgency,
|
|
|
|
| 132 |
It never stores raw or redacted messages, screenshots, links, identifiers,
|
| 133 |
model explanations, reply text, exceptions, or credentials.
|
| 134 |
|
|
|
|
| 128 |
|
| 129 |
Trace creation is deterministic Python logic and makes no additional model
|
| 130 |
request. It records a safe input type or image description, input category,
|
| 131 |
+
urgency, fixed signals, and result counts. The input field uses a safe
|
| 132 |
+
`text: ...` or `image: ...` description generated from fixed templates.
|
| 133 |
It never stores raw or redacted messages, screenshots, links, identifiers,
|
| 134 |
model explanations, reply text, exceptions, or credentials.
|
| 135 |
|
app.py
CHANGED
|
@@ -338,9 +338,6 @@ def analyze_notice(
|
|
| 338 |
text=text,
|
| 339 |
image_data_url=image_data_url,
|
| 340 |
example_id=example_id,
|
| 341 |
-
modal_called=bool(telemetry.get("modal_called", False)),
|
| 342 |
-
modal_ms=float(telemetry.get("modal_ms", 0.0)),
|
| 343 |
-
retry_count=int(telemetry.get("retry_count", 0)),
|
| 344 |
assessment=response.get("assessment"),
|
| 345 |
)
|
| 346 |
response["trace"] = {"trace_id": trace_id, "status": queued}
|
|
|
|
| 338 |
text=text,
|
| 339 |
image_data_url=image_data_url,
|
| 340 |
example_id=example_id,
|
|
|
|
|
|
|
|
|
|
| 341 |
assessment=response.get("assessment"),
|
| 342 |
)
|
| 343 |
response["trace"] = {"trace_id": trace_id, "status": queued}
|
tests/test_tracing.py
CHANGED
|
@@ -27,9 +27,6 @@ class TraceTests(unittest.TestCase):
|
|
| 27 |
),
|
| 28 |
image_data_url="data:image/png;base64,PRIVATE_IMAGE_BYTES",
|
| 29 |
example_id="",
|
| 30 |
-
modal_called=True,
|
| 31 |
-
modal_ms=120,
|
| 32 |
-
retry_count=0,
|
| 33 |
assessment={
|
| 34 |
"risk_label": "Likely scam",
|
| 35 |
"simple_explanation": "PRIVATE MODEL EXPLANATION",
|
|
@@ -67,7 +64,7 @@ class TraceTests(unittest.TestCase):
|
|
| 67 |
|
| 68 |
def test_trace_uses_simplified_columns(self) -> None:
|
| 69 |
image_record = self.sample_record()
|
| 70 |
-
self.assertTrue(image_record["input"].startswith("image
|
| 71 |
self.assertEqual(image_record["input_category"], "unknown")
|
| 72 |
self.assertFalse(image_record["urgency"])
|
| 73 |
for removed in (
|
|
@@ -77,6 +74,11 @@ class TraceTests(unittest.TestCase):
|
|
| 77 |
"failure",
|
| 78 |
"schema_version",
|
| 79 |
"request_source",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
):
|
| 81 |
self.assertNotIn(removed, image_record)
|
| 82 |
|
|
@@ -84,12 +86,12 @@ class TraceTests(unittest.TestCase):
|
|
| 84 |
text="Urgent courier payment required today",
|
| 85 |
image_data_url="",
|
| 86 |
example_id="",
|
| 87 |
-
modal_called=False,
|
| 88 |
-
modal_ms=0,
|
| 89 |
-
retry_count=0,
|
| 90 |
assessment=None,
|
| 91 |
)
|
| 92 |
-
self.assertEqual(
|
|
|
|
|
|
|
|
|
|
| 93 |
self.assertEqual(text_record["input_category"], "courier")
|
| 94 |
self.assertTrue(text_record["urgency"])
|
| 95 |
|
|
@@ -129,7 +131,7 @@ class TraceTests(unittest.TestCase):
|
|
| 129 |
result = app.analyze_notice("test message")
|
| 130 |
self.assertFalse(result["ok"])
|
| 131 |
model_mock.assert_not_called()
|
| 132 |
-
self.
|
| 133 |
|
| 134 |
def test_success_uses_existing_model_call_once(self) -> None:
|
| 135 |
assessment = {
|
|
@@ -162,8 +164,8 @@ class TraceTests(unittest.TestCase):
|
|
| 162 |
result = app.analyze_notice("test message")
|
| 163 |
self.assertTrue(result["ok"])
|
| 164 |
model_mock.assert_called_once()
|
| 165 |
-
self.
|
| 166 |
-
self.
|
| 167 |
|
| 168 |
def test_timeout_is_sanitized(self) -> None:
|
| 169 |
timeout = APITimeoutError(request=httpx.Request("POST", "https://example.invalid"))
|
|
|
|
| 27 |
),
|
| 28 |
image_data_url="data:image/png;base64,PRIVATE_IMAGE_BYTES",
|
| 29 |
example_id="",
|
|
|
|
|
|
|
|
|
|
| 30 |
assessment={
|
| 31 |
"risk_label": "Likely scam",
|
| 32 |
"simple_explanation": "PRIVATE MODEL EXPLANATION",
|
|
|
|
| 64 |
|
| 65 |
def test_trace_uses_simplified_columns(self) -> None:
|
| 66 |
image_record = self.sample_record()
|
| 67 |
+
self.assertTrue(image_record["input"].startswith("image: "))
|
| 68 |
self.assertEqual(image_record["input_category"], "unknown")
|
| 69 |
self.assertFalse(image_record["urgency"])
|
| 70 |
for removed in (
|
|
|
|
| 74 |
"failure",
|
| 75 |
"schema_version",
|
| 76 |
"request_source",
|
| 77 |
+
"text_byte_bucket",
|
| 78 |
+
"text_character_bucket",
|
| 79 |
+
"image_size_bucket",
|
| 80 |
+
"language_hint",
|
| 81 |
+
"modal",
|
| 82 |
):
|
| 83 |
self.assertNotIn(removed, image_record)
|
| 84 |
|
|
|
|
| 86 |
text="Urgent courier payment required today",
|
| 87 |
image_data_url="",
|
| 88 |
example_id="",
|
|
|
|
|
|
|
|
|
|
| 89 |
assessment=None,
|
| 90 |
)
|
| 91 |
+
self.assertEqual(
|
| 92 |
+
text_record["input"],
|
| 93 |
+
"text: Courier-style content with urgency, payment, courier signals",
|
| 94 |
+
)
|
| 95 |
self.assertEqual(text_record["input_category"], "courier")
|
| 96 |
self.assertTrue(text_record["urgency"])
|
| 97 |
|
|
|
|
| 131 |
result = app.analyze_notice("test message")
|
| 132 |
self.assertFalse(result["ok"])
|
| 133 |
model_mock.assert_not_called()
|
| 134 |
+
self.assertNotIn("modal_called", queue_mock.call_args.kwargs)
|
| 135 |
|
| 136 |
def test_success_uses_existing_model_call_once(self) -> None:
|
| 137 |
assessment = {
|
|
|
|
| 164 |
result = app.analyze_notice("test message")
|
| 165 |
self.assertTrue(result["ok"])
|
| 166 |
model_mock.assert_called_once()
|
| 167 |
+
self.assertNotIn("modal_called", queue_mock.call_args.kwargs)
|
| 168 |
+
self.assertNotIn("retry_count", queue_mock.call_args.kwargs)
|
| 169 |
|
| 170 |
def test_timeout_is_sanitized(self) -> None:
|
| 171 |
timeout = APITimeoutError(request=httpx.Request("POST", "https://example.invalid"))
|
traces/data/trace_samples.jsonl
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
-
{"
|
| 2 |
-
{"
|
| 3 |
-
{"
|
| 4 |
-
{"
|
| 5 |
-
{"
|
| 6 |
-
{"
|
|
|
|
| 1 |
+
{"input": "text: Courier-style content with link, urgency, payment, courier signals", "input_category": "courier", "privacy": {"exception_text_stored": false, "identifiers_stored": false, "raw_image_stored": false, "raw_input_stored": false, "raw_model_output_stored": false}, "result": {"red_flag_count": 4, "reply_draft_policy": "suppressed", "reply_draft_returned": false, "risk_label": "Likely scam", "safe_next_step_count": 4}, "signals": {"account_threat": false, "challan": false, "cnic": false, "courier": true, "credentials": false, "link": true, "otp": false, "payment": true, "refund_or_prize": false}, "timestamp": "2026-06-07T06:37:30.001011+00:00", "trace_id": "2d2fda51-9f65-4ffe-a884-a79582de4b86", "urgency": true}
|
| 2 |
+
{"input": "text: FBR-style content with CNIC, credential, urgency, payment signals", "input_category": "fbr", "privacy": {"exception_text_stored": false, "identifiers_stored": false, "raw_image_stored": false, "raw_input_stored": false, "raw_model_output_stored": false}, "result": {"red_flag_count": 4, "reply_draft_policy": "suppressed", "reply_draft_returned": false, "risk_label": "Likely scam", "safe_next_step_count": 4}, "signals": {"account_threat": false, "challan": false, "cnic": true, "courier": false, "credentials": true, "link": false, "otp": false, "payment": true, "refund_or_prize": true}, "timestamp": "2026-06-07T06:37:30.001113+00:00", "trace_id": "57521c66-f3df-412c-8c2f-9638fac910c7", "urgency": true}
|
| 3 |
+
{"input": "text: Bank-style content with OTP, urgency, account-threat signals", "input_category": "bank", "privacy": {"exception_text_stored": false, "identifiers_stored": false, "raw_image_stored": false, "raw_input_stored": false, "raw_model_output_stored": false}, "result": {"red_flag_count": 3, "reply_draft_policy": "suppressed", "reply_draft_returned": false, "risk_label": "Likely scam", "safe_next_step_count": 5}, "signals": {"account_threat": true, "challan": false, "cnic": false, "courier": false, "credentials": false, "link": false, "otp": true, "payment": false, "refund_or_prize": false}, "timestamp": "2026-06-07T06:37:30.001192+00:00", "trace_id": "fa84e753-4492-473f-b797-b94eee8724bc", "urgency": true}
|
| 4 |
+
{"input": "image: Courier-style content with link, urgency, courier signals", "input_category": "courier", "privacy": {"exception_text_stored": false, "identifiers_stored": false, "raw_image_stored": false, "raw_input_stored": false, "raw_model_output_stored": false}, "result": {"red_flag_count": 4, "reply_draft_policy": "suppressed", "reply_draft_returned": false, "risk_label": "Likely scam", "safe_next_step_count": 4}, "signals": {"account_threat": false, "challan": false, "cnic": false, "courier": true, "credentials": false, "link": true, "otp": false, "payment": false, "refund_or_prize": false}, "timestamp": "2026-06-07T06:37:30.001301+00:00", "trace_id": "eaf5013c-adb7-4b06-9e4c-4e785e4c776a", "urgency": true}
|
| 5 |
+
{"input": "image: Marketplace-style content with credential signals", "input_category": "marketplace", "privacy": {"exception_text_stored": false, "identifiers_stored": false, "raw_image_stored": false, "raw_input_stored": false, "raw_model_output_stored": false}, "result": {"red_flag_count": 3, "reply_draft_policy": "suppressed", "reply_draft_returned": false, "risk_label": "Likely scam", "safe_next_step_count": 4}, "signals": {"account_threat": false, "challan": false, "cnic": false, "courier": false, "credentials": true, "link": false, "otp": false, "payment": false, "refund_or_prize": false}, "timestamp": "2026-06-07T06:37:30.001851+00:00", "trace_id": "dd5000f9-d612-4ee8-a1ce-d9c41a8ef347", "urgency": false}
|
| 6 |
+
{"input": "image: Traffic-challan-style content with link, urgency, payment, challan signals", "input_category": "traffic_challan", "privacy": {"exception_text_stored": false, "identifiers_stored": false, "raw_image_stored": false, "raw_input_stored": false, "raw_model_output_stored": false}, "result": {"red_flag_count": 3, "reply_draft_policy": "suppressed", "reply_draft_returned": false, "risk_label": "Likely scam", "safe_next_step_count": 4}, "signals": {"account_threat": false, "challan": true, "cnic": false, "courier": false, "credentials": false, "link": true, "otp": false, "payment": true, "refund_or_prize": false}, "timestamp": "2026-06-07T06:37:30.002064+00:00", "trace_id": "19c0628b-a2ff-45ff-a35e-2a1e6a9d9335", "urgency": true}
|
traces/dataset_card.md
CHANGED
|
@@ -34,18 +34,17 @@ and convert it into allow-listed categories, booleans, buckets, and counts.
|
|
| 34 |
## Fields
|
| 35 |
|
| 36 |
- Trace identity: random trace ID and UTC timestamp
|
| 37 |
-
- `input`:
|
| 38 |
- `input_category`: deterministic category such as courier, bank, or FBR
|
| 39 |
- `urgency`: deterministic boolean urgency signal
|
| 40 |
-
- Size buckets and script/language hint
|
| 41 |
- Deterministic signals: OTP, CNIC, credentials, link, payment,
|
| 42 |
refund/prize, courier, challan, and account threat
|
| 43 |
-
- Modal-call metadata
|
| 44 |
- Final risk label and output item counts
|
| 45 |
- Explicit privacy flags
|
| 46 |
|
| 47 |
Records do not contain pipeline steps, cache fields, app commits, failure
|
| 48 |
-
details, request source,
|
|
|
|
| 49 |
|
| 50 |
## Privacy
|
| 51 |
|
|
|
|
| 34 |
## Fields
|
| 35 |
|
| 36 |
- Trace identity: random trace ID and UTC timestamp
|
| 37 |
+
- `input`: a fixed-template `text: ...` or `image: ...` description
|
| 38 |
- `input_category`: deterministic category such as courier, bank, or FBR
|
| 39 |
- `urgency`: deterministic boolean urgency signal
|
|
|
|
| 40 |
- Deterministic signals: OTP, CNIC, credentials, link, payment,
|
| 41 |
refund/prize, courier, challan, and account threat
|
|
|
|
| 42 |
- Final risk label and output item counts
|
| 43 |
- Explicit privacy flags
|
| 44 |
|
| 45 |
Records do not contain pipeline steps, cache fields, app commits, failure
|
| 46 |
+
details, request source, schema versions, size buckets, language hints, or
|
| 47 |
+
Modal metadata.
|
| 48 |
|
| 49 |
## Privacy
|
| 50 |
|
traces/runtime.py
CHANGED
|
@@ -57,60 +57,6 @@ EXAMPLE_PROFILES = {
|
|
| 57 |
}
|
| 58 |
|
| 59 |
|
| 60 |
-
def _bucket_number(value: float, thresholds: tuple[tuple[float, str], ...]) -> str:
|
| 61 |
-
for maximum, label in thresholds:
|
| 62 |
-
if value <= maximum:
|
| 63 |
-
return label
|
| 64 |
-
return thresholds[-1][1]
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
def duration_bucket(milliseconds: float) -> str:
|
| 68 |
-
return _bucket_number(
|
| 69 |
-
max(0.0, milliseconds),
|
| 70 |
-
(
|
| 71 |
-
(1, "0-1ms"),
|
| 72 |
-
(5, "2-5ms"),
|
| 73 |
-
(10, "6-10ms"),
|
| 74 |
-
(50, "11-50ms"),
|
| 75 |
-
(250, "51-250ms"),
|
| 76 |
-
(1000, "251-1000ms"),
|
| 77 |
-
(5000, "1-5s"),
|
| 78 |
-
(30000, "5-30s"),
|
| 79 |
-
(float("inf"), "30s+"),
|
| 80 |
-
),
|
| 81 |
-
)
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
def input_size_bucket(length: int) -> str:
|
| 85 |
-
return _bucket_number(
|
| 86 |
-
max(0, length),
|
| 87 |
-
(
|
| 88 |
-
(0, "empty"),
|
| 89 |
-
(160, "1-160"),
|
| 90 |
-
(500, "161-500"),
|
| 91 |
-
(2000, "501-2000"),
|
| 92 |
-
(6000, "2001-6000"),
|
| 93 |
-
(12000, "6001-12000"),
|
| 94 |
-
(float("inf"), "12000+"),
|
| 95 |
-
),
|
| 96 |
-
)
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
def image_size_bucket(data_url_length: int) -> str:
|
| 100 |
-
estimated_bytes = max(0, int(data_url_length * 0.75))
|
| 101 |
-
return _bucket_number(
|
| 102 |
-
estimated_bytes,
|
| 103 |
-
(
|
| 104 |
-
(0, "none"),
|
| 105 |
-
(100_000, "up-to-100KB"),
|
| 106 |
-
(500_000, "100-500KB"),
|
| 107 |
-
(2_000_000, "500KB-2MB"),
|
| 108 |
-
(8_000_000, "2-8MB"),
|
| 109 |
-
(float("inf"), "8MB+"),
|
| 110 |
-
),
|
| 111 |
-
)
|
| 112 |
-
|
| 113 |
-
|
| 114 |
def detect_signals(text: str, example_id: str = "") -> dict[str, bool]:
|
| 115 |
detected = {
|
| 116 |
name: bool(re.search(pattern, text or "", re.I | re.S))
|
|
@@ -150,27 +96,6 @@ def detect_category(text: str, signals: dict[str, bool], example_id: str = "") -
|
|
| 150 |
return "unknown"
|
| 151 |
|
| 152 |
|
| 153 |
-
def detect_language_hint(text: str) -> str:
|
| 154 |
-
has_urdu = bool(re.search(r"[\u0600-\u06ff]", text or ""))
|
| 155 |
-
has_latin = bool(re.search(r"[A-Za-z]", text or ""))
|
| 156 |
-
roman_terms = bool(
|
| 157 |
-
re.search(
|
| 158 |
-
r"\b(?:aap|apka|apki|hai|hain|karo|karein|paisa|rupay|bhej|jaldi)\b",
|
| 159 |
-
text or "",
|
| 160 |
-
re.I,
|
| 161 |
-
)
|
| 162 |
-
)
|
| 163 |
-
if has_urdu and has_latin:
|
| 164 |
-
return "mixed_urdu_latin"
|
| 165 |
-
if has_urdu:
|
| 166 |
-
return "urdu_script"
|
| 167 |
-
if roman_terms:
|
| 168 |
-
return "roman_urdu"
|
| 169 |
-
if has_latin:
|
| 170 |
-
return "latin_script"
|
| 171 |
-
return "unknown"
|
| 172 |
-
|
| 173 |
-
|
| 174 |
def safe_description(category: str, signals: dict[str, bool]) -> str:
|
| 175 |
category_labels = {
|
| 176 |
"fbr": "FBR-style",
|
|
@@ -213,17 +138,9 @@ def build_input_profile(text: str, image_data_url: str, example_id: str = "") ->
|
|
| 213 |
signals = detect_signals(text, example_id)
|
| 214 |
category = detect_category(text, signals, example_id)
|
| 215 |
return {
|
| 216 |
-
"input": (
|
| 217 |
-
f"image ({safe_description(category, signals)})"
|
| 218 |
-
if input_type == "image"
|
| 219 |
-
else "text"
|
| 220 |
-
),
|
| 221 |
"input_category": category,
|
| 222 |
"urgency": signals["urgency"],
|
| 223 |
-
"text_character_bucket": input_size_bucket(len(text or "")),
|
| 224 |
-
"text_byte_bucket": input_size_bucket(len((text or "").encode("utf-8"))),
|
| 225 |
-
"image_size_bucket": image_size_bucket(len(image_data_url or "")),
|
| 226 |
-
"language_hint": detect_language_hint(text),
|
| 227 |
"signals": {
|
| 228 |
name: enabled
|
| 229 |
for name, enabled in signals.items()
|
|
@@ -237,9 +154,6 @@ def build_trace_record(
|
|
| 237 |
text: str,
|
| 238 |
image_data_url: str,
|
| 239 |
example_id: str,
|
| 240 |
-
modal_called: bool,
|
| 241 |
-
modal_ms: float,
|
| 242 |
-
retry_count: int,
|
| 243 |
assessment: dict[str, Any] | None,
|
| 244 |
) -> dict[str, Any]:
|
| 245 |
trace_id = str(uuid.uuid4())
|
|
@@ -251,24 +165,6 @@ def build_trace_record(
|
|
| 251 |
"trace_id": trace_id,
|
| 252 |
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 253 |
**input_profile,
|
| 254 |
-
"modal": {
|
| 255 |
-
"called": bool(modal_called),
|
| 256 |
-
"model_family": (
|
| 257 |
-
"qwen3.6-27b-mtp"
|
| 258 |
-
if "qwen3.6-27b-mtp"
|
| 259 |
-
in os.getenv("MODEL_NAME", "qwen3.6-27b-mtp").lower()
|
| 260 |
-
else "other"
|
| 261 |
-
),
|
| 262 |
-
"latency_bucket": duration_bucket(modal_ms),
|
| 263 |
-
"retry_count": max(0, min(int(retry_count), 20)),
|
| 264 |
-
"outcome": (
|
| 265 |
-
"success"
|
| 266 |
-
if modal_called and assessment
|
| 267 |
-
else "failed"
|
| 268 |
-
if modal_called
|
| 269 |
-
else "not_called"
|
| 270 |
-
),
|
| 271 |
-
},
|
| 272 |
"result": {
|
| 273 |
"risk_label": risk_label,
|
| 274 |
"red_flag_count": min(len((assessment or {}).get("red_flags", [])), 50),
|
|
@@ -305,12 +201,7 @@ def validate_trace(record: Any) -> list[str]:
|
|
| 305 |
"input",
|
| 306 |
"input_category",
|
| 307 |
"urgency",
|
| 308 |
-
"text_character_bucket",
|
| 309 |
-
"text_byte_bucket",
|
| 310 |
-
"image_size_bucket",
|
| 311 |
-
"language_hint",
|
| 312 |
"signals",
|
| 313 |
-
"modal",
|
| 314 |
"result",
|
| 315 |
"privacy",
|
| 316 |
}
|
|
@@ -318,12 +209,14 @@ def validate_trace(record: Any) -> list[str]:
|
|
| 318 |
if missing:
|
| 319 |
errors.append("Missing fields: " + ", ".join(sorted(missing)))
|
| 320 |
input_value = record.get("input")
|
| 321 |
-
if
|
| 322 |
isinstance(input_value, str)
|
| 323 |
-
and
|
| 324 |
-
|
|
|
|
|
|
|
| 325 |
):
|
| 326 |
-
errors.append("Input must
|
| 327 |
if not isinstance(record.get("input_category"), str):
|
| 328 |
errors.append("Input category must be a string.")
|
| 329 |
if not isinstance(record.get("urgency"), bool):
|
|
@@ -340,6 +233,11 @@ def validate_trace(record: Any) -> list[str]:
|
|
| 340 |
"pipeline_steps",
|
| 341 |
"cache",
|
| 342 |
"failure",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 343 |
"raw_input",
|
| 344 |
"raw_text",
|
| 345 |
"image_data_url",
|
|
|
|
| 57 |
}
|
| 58 |
|
| 59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
def detect_signals(text: str, example_id: str = "") -> dict[str, bool]:
|
| 61 |
detected = {
|
| 62 |
name: bool(re.search(pattern, text or "", re.I | re.S))
|
|
|
|
| 96 |
return "unknown"
|
| 97 |
|
| 98 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 99 |
def safe_description(category: str, signals: dict[str, bool]) -> str:
|
| 100 |
category_labels = {
|
| 101 |
"fbr": "FBR-style",
|
|
|
|
| 138 |
signals = detect_signals(text, example_id)
|
| 139 |
category = detect_category(text, signals, example_id)
|
| 140 |
return {
|
| 141 |
+
"input": f"{input_type}: {safe_description(category, signals)}",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
"input_category": category,
|
| 143 |
"urgency": signals["urgency"],
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
"signals": {
|
| 145 |
name: enabled
|
| 146 |
for name, enabled in signals.items()
|
|
|
|
| 154 |
text: str,
|
| 155 |
image_data_url: str,
|
| 156 |
example_id: str,
|
|
|
|
|
|
|
|
|
|
| 157 |
assessment: dict[str, Any] | None,
|
| 158 |
) -> dict[str, Any]:
|
| 159 |
trace_id = str(uuid.uuid4())
|
|
|
|
| 165 |
"trace_id": trace_id,
|
| 166 |
"timestamp": datetime.now(timezone.utc).isoformat(),
|
| 167 |
**input_profile,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
"result": {
|
| 169 |
"risk_label": risk_label,
|
| 170 |
"red_flag_count": min(len((assessment or {}).get("red_flags", [])), 50),
|
|
|
|
| 201 |
"input",
|
| 202 |
"input_category",
|
| 203 |
"urgency",
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
"signals",
|
|
|
|
| 205 |
"result",
|
| 206 |
"privacy",
|
| 207 |
}
|
|
|
|
| 209 |
if missing:
|
| 210 |
errors.append("Missing fields: " + ", ".join(sorted(missing)))
|
| 211 |
input_value = record.get("input")
|
| 212 |
+
if not (
|
| 213 |
isinstance(input_value, str)
|
| 214 |
+
and (
|
| 215 |
+
input_value.startswith("text: ")
|
| 216 |
+
or input_value.startswith("image: ")
|
| 217 |
+
)
|
| 218 |
):
|
| 219 |
+
errors.append("Input must use a fixed text: or image: description.")
|
| 220 |
if not isinstance(record.get("input_category"), str):
|
| 221 |
errors.append("Input category must be a string.")
|
| 222 |
if not isinstance(record.get("urgency"), bool):
|
|
|
|
| 233 |
"pipeline_steps",
|
| 234 |
"cache",
|
| 235 |
"failure",
|
| 236 |
+
"text_byte_bucket",
|
| 237 |
+
"text_character_bucket",
|
| 238 |
+
"image_size_bucket",
|
| 239 |
+
"language_hint",
|
| 240 |
+
"modal",
|
| 241 |
"raw_input",
|
| 242 |
"raw_text",
|
| 243 |
"image_data_url",
|
traces/scripts/seed_trace_dataset.py
CHANGED
|
@@ -49,9 +49,6 @@ def build_seed_records() -> list[dict]:
|
|
| 49 |
text=text,
|
| 50 |
image_data_url=image_placeholder,
|
| 51 |
example_id=example_id,
|
| 52 |
-
modal_called=False,
|
| 53 |
-
modal_ms=0,
|
| 54 |
-
retry_count=0,
|
| 55 |
assessment=assessment,
|
| 56 |
)
|
| 57 |
errors = validate_trace(record)
|
|
|
|
| 49 |
text=text,
|
| 50 |
image_data_url=image_placeholder,
|
| 51 |
example_id=example_id,
|
|
|
|
|
|
|
|
|
|
| 52 |
assessment=assessment,
|
| 53 |
)
|
| 54 |
errors = validate_trace(record)
|