fix: bound model stream aggregation and close failed responses
This commit is contained in:
1 parent
4879adc380
commit
7c0c2b59ca
13 files changed
+1315
-12
No files matched your search
@@ -0,0 +1,109 @@
|
||||
"""Summarize actual wire tool constraints without persisting schemas or prompts."""
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
|
||||
from artemis.llm.argument_fingerprint import MAX_TRACKED_TOOLS
|
||||
|
||||
MAX_REQUEST_BYTES = 4 * 1024 * 1024
|
||||
|
||||
|
||||
def safe_label(value):
|
||||
return value if isinstance(value, str) and re.fullmatch(r"[\w.:-]{1,128}", value) else None
|
||||
|
||||
|
||||
def strict_state(tool: dict) -> str:
|
||||
if "strict" not in tool:
|
||||
return "omitted"
|
||||
if tool["strict"] is True:
|
||||
return "true"
|
||||
if tool["strict"] is False:
|
||||
return "false"
|
||||
return "invalid"
|
||||
|
||||
|
||||
def schema_summary(schema: dict) -> dict:
|
||||
"""Count syntactic schema nodes, not expanded $refs or arbitrary examples."""
|
||||
result = {"objects": 0, "optional_properties": 0, "open_objects": 0, "nodes": 0}
|
||||
pending = [schema]
|
||||
while pending and result["nodes"] < 1024:
|
||||
node = pending.pop()
|
||||
result["nodes"] += 1
|
||||
properties = node.get("properties")
|
||||
if node.get("type") == "object" or isinstance(properties, dict):
|
||||
result["objects"] += 1
|
||||
required = node.get("required")
|
||||
required = required if isinstance(required, list) else []
|
||||
if isinstance(properties, dict):
|
||||
result["optional_properties"] += sum(k not in required for k in properties)
|
||||
if node.get("additionalProperties") is not False:
|
||||
result["open_objects"] += 1
|
||||
children = []
|
||||
for key in ("properties", "$defs", "definitions"):
|
||||
if isinstance(node.get(key), dict):
|
||||
children.extend(node[key].values())
|
||||
for key in ("anyOf", "oneOf", "allOf", "prefixItems"):
|
||||
if isinstance(node.get(key), list):
|
||||
children.extend(node[key])
|
||||
children.extend(node.get(k) for k in ("items", "additionalProperties", "not"))
|
||||
remaining = max(0, 1024 - result["nodes"] - len(pending))
|
||||
eligible = [v for v in children if isinstance(v, dict)]
|
||||
if len(eligible) > remaining:
|
||||
result["truncated"] = True
|
||||
pending.extend(eligible[:remaining])
|
||||
result["truncated"] = bool(pending) or result.get("truncated", False)
|
||||
try:
|
||||
result["sha256"] = hashlib.sha256(
|
||||
json.dumps(schema, sort_keys=True, separators=(",", ":"), ensure_ascii=True).encode()
|
||||
).hexdigest()
|
||||
except (RecursionError, TypeError, ValueError):
|
||||
result["sha256"] = None
|
||||
result["truncated"] = True
|
||||
return result
|
||||
|
||||
|
||||
def tool_constraints(tools) -> dict:
|
||||
records = []
|
||||
pending = tools[:MAX_TRACKED_TOOLS] if isinstance(tools, list) else []
|
||||
truncated = isinstance(tools, list) and len(tools) > MAX_TRACKED_TOOLS
|
||||
visited = 0
|
||||
while pending and visited < MAX_TRACKED_TOOLS:
|
||||
tool = pending.pop(0)
|
||||
visited += 1
|
||||
if not isinstance(tool, dict):
|
||||
continue
|
||||
if tool.get("type") == "namespace":
|
||||
nested = tool.get("tools")
|
||||
if isinstance(nested, list):
|
||||
remaining = MAX_TRACKED_TOOLS - len(pending) - visited
|
||||
truncated = truncated or len(nested) > remaining
|
||||
pending.extend(nested[:remaining])
|
||||
continue
|
||||
function = tool.get("function", tool)
|
||||
if not isinstance(function, dict):
|
||||
continue
|
||||
record = {
|
||||
"type": safe_label(tool.get("type")),
|
||||
"name": safe_label(function.get("name")),
|
||||
"strict": strict_state(function),
|
||||
}
|
||||
if isinstance(function.get("parameters"), dict):
|
||||
record["schema"] = schema_summary(function["parameters"])
|
||||
records.append(record)
|
||||
return {"tools": records, "truncated": truncated or bool(pending), "observation": "available"}
|
||||
|
||||
|
||||
def request_constraints(body: bytes) -> dict:
|
||||
if len(body) > MAX_REQUEST_BYTES:
|
||||
return {"observation": "body_too_large"}
|
||||
try:
|
||||
payload = json.loads(body)
|
||||
except (ValueError, UnicodeError, RecursionError):
|
||||
return {"observation": "invalid_json"}
|
||||
if not isinstance(payload, dict):
|
||||
return {"observation": "not_an_object"}
|
||||
result = tool_constraints(payload.get("tools"))
|
||||
limit = payload.get("max_output_tokens")
|
||||
result["max_output_tokens"] = limit if type(limit) is int and limit > 0 else None
|
||||
return result
|
||||
Reference in new issue
Block a user