import argparse
import json
import os
import sys
import pandas as pd
import streamlit as st
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from agentic.data_analysis_env import extract_final_answer, score_agentic_trajectory
from dataset.agentic_dataset import load_agentic_jsonl
DEFAULT_DATA = "dataset/agentic_data/dev.jsonl"
def trajectory_to_text(sample):
chunks = []
for item in sample.get("expert_trajectory", []):
if item.get("role") == "assistant" and item.get("tool_call"):
chunks.append("\n" + json.dumps(item["tool_call"], ensure_ascii=False, indent=2) + "\n")
elif item.get("role") == "assistant":
chunks.append(str(item.get("content", "")))
return "\n---\n".join(chunks)
def parse_turns(text):
if "\n---\n" in text:
return [part.strip() for part in text.split("\n---\n") if part.strip()]
return [text.strip()] if text.strip() else []
def parse_args():
parser = argparse.ArgumentParser(description="Agentic DataAnalysis Streamlit demo")
parser.add_argument("--data", default=DEFAULT_DATA)
parser.add_argument("--repo_root", default=".")
return parser.parse_args()
def main():
args = parse_args()
st.set_page_config(page_title="Agentic DataAnalysis", layout="wide")
st.title("Agentic DataAnalysis")
rows = load_agentic_jsonl(args.data) if os.path.exists(args.data) else []
if not rows:
st.error(f"数据不存在或为空:{args.data}")
return
sample_ids = [row.get("id", str(i)) for i, row in enumerate(rows)]
selected = st.sidebar.selectbox("样本", sample_ids)
sample = rows[sample_ids.index(selected)]
st.subheader("问题")
st.write(sample.get("question", ""))
left, right = st.columns([1.1, 1.0])
with left:
st.subheader("数据表")
st.dataframe(pd.DataFrame(sample.get("tables", [])), use_container_width=True)
st.subheader("指标文档")
st.dataframe(pd.DataFrame(sample.get("documents", [])), use_container_width=True)
with right:
st.subheader("标准答案")
st.write(sample.get("answer", ""))
st.json(sample.get("checks", {}))
st.subheader("期望工具")
st.write(", ".join(sample.get("expected_tools", [])))
st.subheader("轨迹与奖励")
default_text = trajectory_to_text(sample)
trajectory_text = st.text_area("轨迹文本(用 --- 分隔多个 assistant turn 可手动评测模型输出)", value=default_text, height=360)
turn_outputs = [
part
for part in parse_turns(trajectory_text)
if "" not in part
]
reward, parts = score_agentic_trajectory(turn_outputs, sample, repo_root=args.repo_root)
c1, c2, c3, c4, c5 = st.columns(5)
c1.metric("Reward", f"{reward:.3f}")
c2.metric("Success", f"{parts['task_success']:.3f}")
c3.metric("Tool F1", f"{parts['tool_selection_f1']:.3f}")
c4.metric("Invalid", f"{parts['invalid_action_rate']:.3f}")
c5.metric("Turns", f"{parts['avg_turns']:.1f}")
st.subheader("Reward 分解")
st.dataframe(pd.DataFrame([parts]).T.rename(columns={0: "score"}), use_container_width=True)
st.subheader("Final Answer")
st.write(extract_final_answer(turn_outputs))
if __name__ == "__main__":
main()