Trong hướng dẫn này, chúng tôi khám phá AgentTrove, một trong những bộ sưu tập mã nguồn mở lớn nhất về dấu vết tương tác của tác nhân (agentic interaction traces), và tìm hiểu cách làm việc hiệu quả với nó. Thay vì tải xuống toàn bộ tập dữ liệu, chúng tôi sử dụng phương pháp truyền dữ liệu (streaming) để kiểm tra các hàng, phát hiện lược đồ hội thoại, chuẩn hóa các lượt của tác nhân và hiểu cấu trúc của các tin nhắn từ người dùng, trợ lý, hệ thống và công cụ. Chúng tôi cũng xây dựng các tiện ích để phân tích đầu ra của trợ lý theo kiểu lệnh, hiển thị toàn bộ quỹ đạo theo định dạng dễ đọc và nghiên cứu cách các tác nhân tương tác với các công cụ trong các tác vụ khác nhau. Ngoài ra, chúng tôi tạo ra một quy trình làm việc phân tích nhẹ.
Trong hướng dẫn này, chúng ta sẽ khám phá AgentTrove, một trong những bộ sưu tập mã nguồn mở lớn nhất về các dấu vết tương tác của tác nhân (agentic interaction traces), và tìm hiểu cách làm việc hiệu quả với nó. Thay vì tải xuống toàn bộ tập dữ liệu, chúng ta sử dụng tính năng truyền trực tuyến (streaming) để kiểm tra các hàng, phát hiện lược đồ hội thoại, chuẩn hóa các lượt của tác nhân và hiểu cách các thông báo của người dùng, trợ lý, hệ thống và công cụ được cấu trúc. Chúng ta cũng xây dựng các tiện ích để phân tích đầu ra của trợ lý theo kiểu lệnh, hiển thị toàn bộ quỹ đạo ở định dạng dễ đọc và nghiên cứu cách các tác nhân tương tác với các công cụ trong các tác vụ khác nhau. Ngoài ra, chúng ta tạo một quy trình làm việc phân tích nhẹ, lấy mẫu hàng nghìn dấu vết, chuyển đổi chúng thành DataFrame, tóm tắt các thống kê cấp lượt, trực quan hóa các mẫu tập dữ liệu quan trọng và xuất các dấu vết thành công sang định dạng JSONL kiểu ShareGPT sạch để tinh chỉnh có giám sát.
!pip -q install "datasets>=2.19" pandas matplotlib pyarrow huggingface_hub
import itertools, json, collections, textwrap, re, random, statistics
import pandas as pd
import matplotlib.pyplot as plt
from datasets import load_dataset
REPO = "open-thoughts/AgentTrove"
random.seed(0)
print(" Imports ready. Target dataset:", REPO)
ds = load_dataset(REPO, split="train", streaming=True)
print(" Streaming dataset opened.")
first = next(iter(ds))
print("\n Columns present in a row:")
for k in first.keys():
v = first[k]
t = type(v).__name__
preview = (str(v)[:70] + "…") if v is not None and len(str(v)) > 70 else v
print(f" • {k:<18} ({t}): {preview}")
Chúng ta cài đặt các thư viện cần thiết và nhập các công cụ cốt lõi cần thiết cho việc truyền trực tuyến, phân tích và trực quan hóa. Chúng ta định nghĩa kho lưu trữ AgentTrove, mở tập dữ liệu ở chế độ truyền trực tuyến và tránh tải xuống toàn bộ tập dữ liệu cục bộ. Sau đó, chúng ta kiểm tra hàng đầu tiên để hiểu các cột có sẵn và có cái nhìn ban đầu về lược đồ tập dữ liệu.
def find_trace_key(row):
for cand in ("conversations", "messages"):
if cand in row and isinstance(row[cand], list):
return cand
for k, v in row.items():
if isinstance(v, list) and v and isinstance(v[0], dict) and \
("content" in v[0] or "role" in v[0] or "value" in v[0]):
return k
raise KeyError("No conversation-like column found.")
TRACE_KEY = find_trace_key(first)
print(f"\n Trace column detected: '{TRACE_KEY}'")
def normalize_turns(trace):
turns = []
for turn in trace:
if not isinstance(turn, dict):
turns.append(("unknown", str(turn)))
continue
role = turn.get("role") or turn.get("from") or "unknown"
content = turn.get("content")
if content is None:
content = turn.get("value", "")
turns.append((str(role), "" if content is None else str(content)))
return turns
sample_turns = normalize_turns(first[TRACE_KEY])
print(f" First trace has {len(sample_turns)} turns. "
f"Roles: {collections.Counter(r for r, _ in sample_turns)}")
Chúng ta tạo một hàm phòng ngừa để tự động phát hiện cột chứa dữ liệu hội thoại hoặc dấu vết. Sau đó, chúng ta chuẩn hóa mỗi lượt thành định dạng vai trò-nội dung nhất quán để có thể xử lý trơn tru các lược đồ tập dữ liệu khác nhau. Chúng ta cũng kiểm tra quỹ đạo đầu tiên để đếm số lượt và hiểu các vai trò có trong cuộc hội thoại.
def extract_commands(assistant_content):
"""Nỗ lực tốt nhất: trích xuất các lệnh shell từ một lượt JSON của trợ lý."""
cmds = []
txt = re.sub(r"```(?:json)?|```", "", assistant_content).strip()
try:
obj = json.loads(txt)
except Exception:
return cmds
def walk(o):
if isinstance(o, dict):
for key in ("commands", "command", "keystrokes", "cmd", "action"):
if key in o:
val = o[key]
if isinstance(val, str):
cmds.append(val.strip())
elif isinstance(val, list):
for item in val:
if isinstance(item, str):
cmds.append(item.strip())
elif isinstance(item, dict):
walk(item)
for v in o.values():
if isinstance(v, (dict, list)):
walk(v)
elif isinstance(o, list):
for v in o:
walk(v)
walk(obj)
return [c for c in cmds if c]
Chúng tôi định nghĩa một tiện ích trích xuất lệnh đọc phản hồi của trợ lý và cố gắng phân tích các lệnh shell từ các đầu ra kiểu JSON. Chúng tôi loại bỏ các dấu phân cách mã có thể có, tải nội dung dưới dạng JSON và tìm kiếm đệ quy thông qua các trường liên quan đến lệnh phổ biến. Điều này giúp chúng tôi xác định các hành động giống công cụ trong các quỹ đạo của tác nhân và đo lường tần suất các tác nhân đưa ra các lệnh có thể thực thi.
def render_trace(row, max_chars=600):
meta = {k: row.get(k) for k in
("original_source", "original_teacher", "model", "task",
"result", "reward", "model_provider") if k in row}
print("=" * 78)
print(" METADATA:", {k: v for k, v in meta.items() if v is not None})
print("=" * 78)
for i, (role, content) in enumerate(normalize_turns(row[TRACE_KEY])):
tag = {"system": " SYSTEM", "user": " USER",
"assistant": " ASSISTANT", "tool": " TOOL"}.get(role, f" {role.upper()}")
snippet = content if len(content) <= max_chars else content[:max_chars] + " …[truncated]"
print(f"\n[{i}] {tag}")
print(textwrap.indent(snippet, " "))
if role == "assistant":
for c in extract_commands(content)[:5]:
print(f" └─ parsed command: {c!r}")
print("=" * 78, "\n")
print("\n EXAMPLE TRAJECTORY (first row):")
render_trace(first, max_chars=400)
Chúng tôi xây dựng một hàm hiển thị dấu vết, in siêu dữ liệu và toàn bộ quỹ đạo hội thoại theo định dạng dễ đọc. Chúng tôi gắn nhãn mỗi lượt theo vai trò, cắt bớt các tin nhắn dài để dễ hiểu và hiển thị các lệnh đã phân tích dưới các tin nhắn của trợ lý.
N = 2000
records = []
print(f"\n Đang truyền phát {N} hàng để phân tích…")
for row in itertools.islice(load_dataset(REPO, split="train", streaming=True), N):
turns = normalize_turns(row[TRACE_KEY])
roles = collections.Counter(r for r, _ in turns)
total_chars = sum(len(c) for _, c in turns)
asst_cmds = sum(len(extract_commands(c)) for r, c in turns if r == "assistant")
records.append({
"original_source": row.get("original_source"),
"original_teacher": row.get(
Nguồn tin: MarkTechPost — Tác giả: Sana Hassan. Bản dịch tiếng Việt do AI thực hiện, có thể có sai sót.