Skip to content

Commit 056b3e0

Browse files
Implement cost and latency tracking (GH-10)
2 parents 472f999 + 0859519 commit 056b3e0

File tree

13 files changed

+25984
-52
lines changed

13 files changed

+25984
-52
lines changed

README.md

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ especially useful when working with large networks: graphs with many nodes, bran
1111
reason about from the logs alone.
1212

1313
<p align="center">
14-
<img alt="Demo" src="https://github.com/user-attachments/assets/1db519fb-0dd9-4fee-8bc8-f6b12cbf1342" width="80%">
14+
<img alt="Demo" src="https://github.com/user-attachments/assets/1db519fb-0dd9-4fee-8bc8-f6b12cbf1342" width="800px">
1515
</p>
1616

1717
## Why it helps
@@ -43,26 +43,22 @@ it in while you're actively building - it has no effect on how the agent behaves
4343

4444
## Features
4545

46-
| Feature | [LangGraphics](https://github.com/proactive-agent/langgraphics) | [LangFuse](https://github.com/langfuse/langfuse) | [LangSmith Studio](https://smith.langchain.com) |
47-
|------------------------------------|-----------------------------------------------------------------|--------------------------------------------------|-------------------------------------------------|
48-
| Open-source ||||
49-
| Unlimited free usage ||||
50-
| Self-hosting supported ||||
51-
| No vendor lock-in ||||
52-
| Works without external services ||||
53-
| Simple setup ||||
54-
| One-line integration ||||
55-
| No API key required ||||
56-
| No instrumentation required ||||
57-
| Runs fully locally ||||
58-
| Native LangGraph visualization ||||
59-
| Real-time execution graph ||||
60-
| Data stays local by default ||||
61-
| Low learning curve ||||
62-
| Built-in prompt evaluation ||||
63-
| Built-in observability dashboards ||||
64-
| Built-in cost and latency tracking ||||
65-
| Production monitoring capabilities ||||
46+
| Feature | [LangGraphics](https://github.com/proactive-agent/langgraphics) | [LangFuse](https://github.com/langfuse/langfuse) | [LangSmith](https://smith.langchain.com) |
47+
|-------------------------|----------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------|
48+
| Fully local | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
49+
| Standalone | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
50+
| Easy to learn | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
51+
| One-line setup | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
52+
| Data stays local | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
53+
| No API key required | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
54+
| Live execution graph | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
55+
| No refactoring required | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
56+
| Self-hosted | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
57+
| No vendor lock-in | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
58+
| Unlimited free usage | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) |
59+
| Graph visualization | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) |
60+
| Cost & latency tracking | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) |
61+
| Prompt evaluation | ![🟥](https://github.com/user-attachments/assets/ebe12afc-ae2e-42b1-a058-e93353ff87c4) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) | ![](https://github.com/user-attachments/assets/b3c25b41-567c-4c26-bc02-ee3e40fd57c1) |
6662

6763
## Contribute
6864

langgraphics-web/src/components/GraphCanvas.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import {type ReactNode, useCallback, useEffect, useState} from "react";
1+
import {useCallback, useEffect, useState} from "react";
22
import {Background, type ColorMode, type Edge, type Node, type NodeTypes, ReactFlow} from "@xyflow/react";
33
import {Controls} from "./Controls";
44
import {CustomNode} from "./CustomNode";
55
import {useFocus} from "../hooks/useFocus";
6-
import type {EdgeData, ExecutionEvent, InspectorMode, NodeData, ViewMode} from "../types";
6+
import {InspectPanel} from "./InspectPanel";
7+
import type {EdgeData, ExecutionEvent, InspectorMode, NodeData, NodeEntry, ViewMode} from "../types";
78
import type {RankDir} from "../layout";
89

910
const nodeTypes: NodeTypes = {custom: CustomNode as NodeTypes[string]};
@@ -12,16 +13,16 @@ interface GraphCanvasProps {
1213
nodes: Node<NodeData>[];
1314
edges: Edge<EdgeData>[];
1415
events: ExecutionEvent[];
16+
nodeEntries: NodeEntry[];
1517
activeNodeIds: string[];
16-
inspect: ReactNode;
1718
initialMode: ViewMode;
1819
initialRankDir?: RankDir;
1920
initialColorMode?: ColorMode;
2021
initialInspect?: InspectorMode;
2122
onRankDirChange?: (v: RankDir) => void;
2223
}
2324

24-
export function GraphCanvas({nodes, edges, events, activeNodeIds, inspect, initialMode = "auto", initialInspect = "off", initialColorMode = "system", initialRankDir = "TB", onRankDirChange}: GraphCanvasProps) {
25+
export function GraphCanvas({nodes, edges, events, activeNodeIds, nodeEntries, initialMode = "auto", initialInspect = "off", initialColorMode = "system", initialRankDir = "TB", onRankDirChange}: GraphCanvasProps) {
2526
const [rankDir, setRankDir] = useState<RankDir>(initialRankDir);
2627
const [colorMode, setColorMode] = useState<ColorMode>(initialColorMode);
2728
const [inspectorMode, setInspectorMode] = useState<InspectorMode>(initialInspect);
@@ -65,7 +66,10 @@ export function GraphCanvas({nodes, edges, events, activeNodeIds, inspect, initi
6566
/>
6667
<Background/>
6768
<div className={`inspect-wrapper-${inspectorMode}`}>
68-
{inspect}
69+
<InspectPanel
70+
colorMode={colorMode}
71+
nodeEntries={nodeEntries}
72+
/>
6973
</div>
7074
</ReactFlow>
7175
);

langgraphics-web/src/components/InspectPanel.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import Tree from "antd/es/tree";
22
import type {TreeDataNode} from "antd";
33
import ReactMarkdown from "react-markdown";
4+
import type {ColorMode} from "@xyflow/react";
45
import {useCallback, useEffect, useMemo, useState} from "react";
56
import type {NodeEntry} from "../types";
7+
import {Metrics} from "./Metrics";
68

7-
export function InspectPanel({nodeEntries}: { nodeEntries: NodeEntry[] }) {
9+
export function InspectPanel({colorMode, nodeEntries}: { colorMode: ColorMode, nodeEntries: NodeEntry[] }) {
810
const [selectedKey, setSelectedKey] = useState<string>("");
911

1012
const expandedKeys = useMemo(() => {
@@ -100,6 +102,12 @@ export function InspectPanel({nodeEntries}: { nodeEntries: NodeEntry[] }) {
100102
<div className="inspect-detail-pane">
101103
{selectedEntry && (
102104
<>
105+
{selectedEntry.metrics && (
106+
<Metrics
107+
colorMode={colorMode}
108+
metrics={selectedEntry.metrics}
109+
/>
110+
)}
103111
{system && (
104112
<div className="inspect-detail-section">
105113
<span className={`inspect-section-label ${system.role ?? ""}`}>

0 commit comments

Comments
 (0)