Spaces:
Running
Running
File size: 4,573 Bytes
c2ea5ed |
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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
import React, { useMemo } from "react";
import { useAgentGraph } from "@/context/AgentGraphContext";
interface EntityRelationTreeChartProps {
className?: string;
}
interface ChartData {
name: string;
count: number;
color: string;
type: "entity" | "relation";
}
export function EntityRelationTreeChart({
className,
}: EntityRelationTreeChartProps) {
const { state } = useAgentGraph();
// Process data to get entity and relation type distributions
const chartData = useMemo(() => {
const entityTypes = new Map<string, number>();
const relationTypes = new Map<string, number>();
state.traces.forEach((trace) => {
trace.knowledge_graphs?.forEach((kg: any) => {
if (kg.graph_data) {
try {
const graphData =
typeof kg.graph_data === "string"
? JSON.parse(kg.graph_data)
: kg.graph_data;
// Count entity types
if (graphData.entities && Array.isArray(graphData.entities)) {
graphData.entities.forEach((entity: any) => {
const type = entity.type || "Unknown";
entityTypes.set(type, (entityTypes.get(type) || 0) + 1);
});
}
// Count relation types
if (graphData.relations && Array.isArray(graphData.relations)) {
graphData.relations.forEach((relation: any) => {
const type = relation.type || "Unknown";
relationTypes.set(type, (relationTypes.get(type) || 0) + 1);
});
}
} catch (error) {
console.warn("Error parsing graph_data:", error);
}
}
});
});
// Entity type colors
const entityColors = {
Agent: "#3b82f6",
Task: "#10b981",
Tool: "#f59e0b",
Input: "#8b5cf6",
Output: "#ef4444",
Human: "#06b6d4",
Unknown: "#6b7280",
};
// Relation type colors (using different shades)
const relationColors = {
CONSUMED_BY: "#93c5fd",
PERFORMS: "#86efac",
ASSIGNED_TO: "#fbbf24",
USES: "#c4b5fd",
REQUIRED_BY: "#fca5a5",
SUBTASK_OF: "#67e8f9",
NEXT: "#a78bfa",
PRODUCES: "#34d399",
DELIVERS_TO: "#60a5fa",
INTERVENES: "#fb7185",
Unknown: "#9ca3af",
};
const data: ChartData[] = [];
// Add entity type data
entityTypes.forEach((count, type) => {
data.push({
name: type,
count,
color:
entityColors[type as keyof typeof entityColors] ||
entityColors.Unknown,
type: "entity",
});
});
// Add relation type data
relationTypes.forEach((count, type) => {
data.push({
name: type.replace(/_/g, " "), // Make relation names more readable
count,
color:
relationColors[type as keyof typeof relationColors] ||
relationColors.Unknown,
type: "relation",
});
});
// Sort by count descending and take top 8 to fit in the space
return data.sort((a, b) => b.count - a.count).slice(0, 8);
}, [state.traces]);
if (chartData.length === 0) {
return (
<div
className={`h-20 w-full flex items-center justify-center ${className}`}
>
<div className="text-xs text-muted-foreground/50">No graph data</div>
</div>
);
}
// Calculate max count for scaling
const maxCount = Math.max(...chartData.map((d) => d.count));
return (
<div
className={`h-20 w-full flex items-end justify-center gap-1 px-2 ${className}`}
>
{chartData.map((item, index) => {
const height = Math.max(8, (item.count / maxCount) * 60); // Min height 8px, max 60px
return (
<div
key={`${item.type}-${item.name}-${index}`}
className="flex flex-col items-center justify-end flex-1 min-w-0"
title={`${item.name}: ${item.count}`}
>
{/* Bar */}
<div
className="w-full rounded-t-sm transition-all duration-300 hover:opacity-80"
style={{
height: `${height}px`,
backgroundColor: item.color,
boxShadow: `0 0 4px ${item.color}40`,
}}
/>
{/* Label */}
<div className="text-[8px] text-muted-foreground/70 mt-1 truncate w-full text-center font-medium">
{item.name.length > 6 ? `${item.name.slice(0, 5)}...` : item.name}
</div>
</div>
);
})}
</div>
);
}
|