Repository navigation
Expand file tree
/
Copy pathtelemetry.py
More file actions
69 lines (60 loc) · 2.06 KB
/
Copy pathtelemetry.py
File metadata and controls
69 lines (60 loc) · 2.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import json
import time
from pathlib import Path
from typing import List
LOG_FILE = Path("agent_metrics.jsonl")
def log_agent_turn(
session_id: str,
prompt: str,
tool_calls: List[dict],
tokens_used: int,
ast_intercepted: bool,
context_size_before: int,
context_size_after: int,
):
"""
在 Agent 的核心循环(每轮大模型返回结果后)调用此函数埋点。
参数说明:
- session_id: 会话唯一 id
- prompt: 模型输入文本(或摘要)
- tool_calls: 模型请求的工具调用列表(字典,包含 name/args)
- tokens_used: 本轮消耗的 token 数(若可用)
- ast_intercepted: 是否触发 AST 语法拦截
- context_size_before/after: 压缩前后的上下文大小(字符数或 token)
"""
try:
ratio = (
(context_size_before - context_size_after) / context_size_before
if context_size_before > 0
else 0
)
except Exception:
ratio = 0
log_entry = {
"timestamp": time.time(),
"session_id": session_id,
"prompt_length": len(prompt) if prompt is not None else 0,
"tools_called": [t.get("name") for t in tool_calls] if tool_calls else [],
"tokens_used": tokens_used,
"ast_intercepted": bool(ast_intercepted),
"context_compression_ratio": ratio,
}
try:
LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(json.dumps(log_entry, ensure_ascii=False) + "\n")
except Exception as e:
# 埋点不应抛出异常影响主流程,故捕获并打印
print(f"[telemetry] 写入失败: {e}")
def read_all_logs() -> List[dict]:
"""返回所有已记录的埋点(仅供离线分析/调试)。"""
if not LOG_FILE.exists():
return []
out = []
with open(LOG_FILE, "r", encoding="utf-8") as f:
for line in f:
try:
out.append(json.loads(line))
except Exception:
continue
return out