hedit 0.7.5.dev2__tar.gz → 0.7.6.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hedit-0.7.5.dev2/hedit.egg-info → hedit-0.7.6.dev1}/PKG-INFO +1 -1
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1/hedit.egg-info}/PKG-INFO +1 -1
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/pyproject.toml +1 -1
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/workflow.py +31 -28
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/api/main.py +27 -17
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/version.py +2 -2
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/LICENSE +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/PKG_README.md +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/README.md +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/hedit.egg-info/SOURCES.txt +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/hedit.egg-info/dependency_links.txt +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/hedit.egg-info/entry_points.txt +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/hedit.egg-info/requires.txt +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/hedit.egg-info/top_level.txt +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/setup.cfg +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/annotation_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/assessment_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/evaluation_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/feedback_summarizer.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/feedback_triage_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/state.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/validation_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/agents/vision_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/api/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/api/models.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/api/security.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/api_executor.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/client.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/commands/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/config.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/executor.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/local_executor.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/main.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/cli/output.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/scripts/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/scripts/process_feedback.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/telemetry/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/telemetry/collector.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/telemetry/schema.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/telemetry/storage.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/error_remediation.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/github_client.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/hed_comprehensive_guide.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/hed_rules.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/image_processing.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/json_schema_loader.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/litellm_llm.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/openrouter_llm.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/utils/schema_loader.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/validation/__init__.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/validation/hed_lsp.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/src/validation/hed_validator.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_annotation_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_api_endpoints.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_cli_client.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_cli_config.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_cli_integration.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_cli_main.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_comprehensive_guide.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_error_remediation.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_feedback_integration.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_feedback_triage.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_github_client.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_hed_lsp.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_integration_openrouter.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_json_schema_loader.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_keyword_extraction.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_litellm_llm.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_no_extend_propagation.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_openrouter_llm.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_schema_loader.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_security.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_state.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_telemetry.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_validation.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_validation_agent.py +0 -0
- {hedit-0.7.5.dev2 → hedit-0.7.6.dev1}/tests/test_version.py +0 -0
|
@@ -4,6 +4,7 @@ This module defines the multi-agent workflow that orchestrates
|
|
|
4
4
|
annotation, validation, evaluation, and assessment.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import asyncio
|
|
7
8
|
import logging
|
|
8
9
|
import time
|
|
9
10
|
from pathlib import Path
|
|
@@ -239,28 +240,32 @@ class HedAnnotationWorkflow:
|
|
|
239
240
|
semantic_hints: list[dict] = []
|
|
240
241
|
|
|
241
242
|
if keywords and self.hed_lsp_client:
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
result = self.hed_lsp_client.suggest
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
"[WORKFLOW] hed-lsp suggestion failed for '%s': %s",
|
|
259
|
-
keyword,
|
|
260
|
-
result.error,
|
|
243
|
+
# Query hed-lsp for each keyword individually for better results
|
|
244
|
+
for keyword in keywords:
|
|
245
|
+
try:
|
|
246
|
+
result = await asyncio.to_thread(self.hed_lsp_client.suggest, keyword)
|
|
247
|
+
except Exception as e:
|
|
248
|
+
logger.warning("[WORKFLOW] hed-lsp error for '%s': %s", keyword, e)
|
|
249
|
+
continue
|
|
250
|
+
if result.success:
|
|
251
|
+
for s in result.suggestions:
|
|
252
|
+
semantic_hints.append(
|
|
253
|
+
{
|
|
254
|
+
"tag": s.tag,
|
|
255
|
+
"keyword": keyword,
|
|
256
|
+
"score": s.score or 0.0,
|
|
257
|
+
"source": "hed-lsp",
|
|
258
|
+
}
|
|
261
259
|
)
|
|
262
|
-
|
|
263
|
-
|
|
260
|
+
else:
|
|
261
|
+
logger.debug(
|
|
262
|
+
"[WORKFLOW] hed-lsp suggestion failed for '%s': %s",
|
|
263
|
+
keyword,
|
|
264
|
+
result.error,
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
# Deduplicate by tag, keeping highest score
|
|
268
|
+
if semantic_hints:
|
|
264
269
|
seen_tags: dict[str, dict] = {}
|
|
265
270
|
for hint in semantic_hints:
|
|
266
271
|
tag = hint["tag"]
|
|
@@ -268,13 +273,11 @@ class HedAnnotationWorkflow:
|
|
|
268
273
|
seen_tags[tag] = hint
|
|
269
274
|
semantic_hints = sorted(seen_tags.values(), key=lambda h: h["score"], reverse=True)
|
|
270
275
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
except Exception as e:
|
|
277
|
-
logger.warning("[WORKFLOW] hed-lsp error: %s", e, exc_info=True)
|
|
276
|
+
logger.info(
|
|
277
|
+
"[WORKFLOW] hed-lsp suggested %d unique tags from %d keywords",
|
|
278
|
+
len(semantic_hints),
|
|
279
|
+
len(keywords),
|
|
280
|
+
)
|
|
278
281
|
elif keywords:
|
|
279
282
|
# LSP not available; still store keywords for the annotation agent
|
|
280
283
|
logger.info(
|
|
@@ -668,11 +668,16 @@ async def annotate(
|
|
|
668
668
|
or req.headers.get("x-openrouter-model")
|
|
669
669
|
or os.getenv("ANNOTATION_MODEL", "openai/gpt-oss-120b")
|
|
670
670
|
)
|
|
671
|
-
temperature =
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
671
|
+
temperature = request.temperature
|
|
672
|
+
if temperature is None:
|
|
673
|
+
temp_header = req.headers.get("x-openrouter-temperature")
|
|
674
|
+
if temp_header is not None:
|
|
675
|
+
try:
|
|
676
|
+
temperature = float(temp_header)
|
|
677
|
+
except ValueError:
|
|
678
|
+
temperature = None
|
|
679
|
+
if temperature is None:
|
|
680
|
+
temperature = _byok_config.get("temperature", 0.1)
|
|
676
681
|
|
|
677
682
|
event = TelemetryEvent.create(
|
|
678
683
|
description=request.description,
|
|
@@ -874,11 +879,16 @@ async def annotate_from_image(
|
|
|
874
879
|
or req.headers.get("x-openrouter-model")
|
|
875
880
|
or os.getenv("ANNOTATION_MODEL", "openai/gpt-oss-120b")
|
|
876
881
|
)
|
|
877
|
-
temperature =
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
+
temperature = request.temperature
|
|
883
|
+
if temperature is None:
|
|
884
|
+
temp_header = req.headers.get("x-openrouter-temperature")
|
|
885
|
+
if temp_header is not None:
|
|
886
|
+
try:
|
|
887
|
+
temperature = float(temp_header)
|
|
888
|
+
except ValueError:
|
|
889
|
+
temperature = None
|
|
890
|
+
if temperature is None:
|
|
891
|
+
temperature = _byok_config.get("temperature", 0.1)
|
|
882
892
|
|
|
883
893
|
event = TelemetryEvent.create(
|
|
884
894
|
description=image_description, # Use generated image description
|
|
@@ -1204,7 +1214,7 @@ async def annotate_stream(
|
|
|
1204
1214
|
description=request.description,
|
|
1205
1215
|
)
|
|
1206
1216
|
except Exception:
|
|
1207
|
-
logging.
|
|
1217
|
+
logging.warning("Telemetry collection failed for streaming request", exc_info=True)
|
|
1208
1218
|
|
|
1209
1219
|
yield send_event("done", {"message": "Workflow completed"})
|
|
1210
1220
|
|
|
@@ -1230,7 +1240,7 @@ async def annotate_stream(
|
|
|
1230
1240
|
description=request.description,
|
|
1231
1241
|
)
|
|
1232
1242
|
except Exception:
|
|
1233
|
-
logging.
|
|
1243
|
+
logging.warning("Telemetry collection failed on timeout", exc_info=True)
|
|
1234
1244
|
yield send_event("done", {"message": "Workflow ended with error"})
|
|
1235
1245
|
except RateLimitError:
|
|
1236
1246
|
logging.exception("Streaming workflow rate limit")
|
|
@@ -1252,7 +1262,7 @@ async def annotate_stream(
|
|
|
1252
1262
|
description=request.description,
|
|
1253
1263
|
)
|
|
1254
1264
|
except Exception:
|
|
1255
|
-
logging.
|
|
1265
|
+
logging.warning("Telemetry collection failed on rate limit", exc_info=True)
|
|
1256
1266
|
yield send_event("done", {"message": "Workflow ended with error"})
|
|
1257
1267
|
except Exception:
|
|
1258
1268
|
logging.exception("Streaming workflow error")
|
|
@@ -1274,7 +1284,7 @@ async def annotate_stream(
|
|
|
1274
1284
|
description=request.description,
|
|
1275
1285
|
)
|
|
1276
1286
|
except Exception:
|
|
1277
|
-
logging.
|
|
1287
|
+
logging.warning("Telemetry collection failed on error", exc_info=True)
|
|
1278
1288
|
yield send_event("done", {"message": "Workflow ended with error"})
|
|
1279
1289
|
|
|
1280
1290
|
return StreamingResponse(
|
|
@@ -1583,7 +1593,7 @@ async def annotate_from_image_stream(
|
|
|
1583
1593
|
description=image_description or "image-annotation-failed",
|
|
1584
1594
|
)
|
|
1585
1595
|
except Exception:
|
|
1586
|
-
logging.
|
|
1596
|
+
logging.warning("Telemetry collection failed on image timeout", exc_info=True)
|
|
1587
1597
|
yield send_event("done", {"message": "Workflow ended with error"})
|
|
1588
1598
|
except RateLimitError:
|
|
1589
1599
|
logging.exception("Streaming image workflow rate limit")
|
|
@@ -1605,7 +1615,7 @@ async def annotate_from_image_stream(
|
|
|
1605
1615
|
description=image_description or "image-annotation-failed",
|
|
1606
1616
|
)
|
|
1607
1617
|
except Exception:
|
|
1608
|
-
logging.
|
|
1618
|
+
logging.warning("Telemetry collection failed on image rate limit", exc_info=True)
|
|
1609
1619
|
yield send_event("done", {"message": "Workflow ended with error"})
|
|
1610
1620
|
except Exception:
|
|
1611
1621
|
logging.exception("Streaming image annotation workflow error")
|
|
@@ -1627,7 +1637,7 @@ async def annotate_from_image_stream(
|
|
|
1627
1637
|
description=image_description or "image-annotation-failed",
|
|
1628
1638
|
)
|
|
1629
1639
|
except Exception:
|
|
1630
|
-
logging.
|
|
1640
|
+
logging.warning("Telemetry collection failed on image error", exc_info=True)
|
|
1631
1641
|
yield send_event("done", {"message": "Workflow ended with error"})
|
|
1632
1642
|
|
|
1633
1643
|
return StreamingResponse(
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|