Skip to content

Commit

Permalink
Release 1.1.2 (#74)
Browse files Browse the repository at this point in the history
* Pagination bug

* Bug fix

* chore: add docker cmd

* Compatibility fixes for SDK version 2.0.0 (#69)

* Pagination bug

* Bug fix

* Fix for schema changes

* Render tool calling

* Support for Langgraph, Qdrant & Groq  (#73)

* Pagination bug

* Bug fix

* Add langgraph support

* QDrant support

* Add Groq support

* update README

* update README

---------

Co-authored-by: Darshit Suratwala <[email protected]>
Co-authored-by: darshit-s3 <[email protected]>
  • Loading branch information
3 people authored Apr 28, 2024
1 parent 68ccb8b commit 5942844
Show file tree
Hide file tree
Showing 11 changed files with 595 additions and 23 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ COPY . .
RUN npm install

EXPOSE 3000

CMD [ "/bin/sh", "-c", "npm run create-tables && npm run dev" ]
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,13 @@ Langtrace automatically captures traces from the following vendors:
| OpenAI | LLM | :white_check_mark: | :white_check_mark: |
| Anthropic | LLM | :white_check_mark: | :white_check_mark: |
| Azure OpenAI | LLM | :white_check_mark: | :white_check_mark: |
| Cohere | LLM | :white_check_mark: | :white_check_mark: |
| Groq | LLM | :x: | :white_check_mark: |
| Langchain | Framework | :x: | :white_check_mark: |
| LlamaIndex | Framework | :white_check_mark: | :white_check_mark: |
| Pinecone | Vector Database | :white_check_mark: | :white_check_mark: |
| ChromaDB | Vector Database | :white_check_mark: | :white_check_mark: |
| QDrant | Vector Database | :x: | :white_check_mark: |

---

Expand Down
34 changes: 33 additions & 1 deletion components/project/traces/trace-row.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import LanggraphView from "@/components/shared/langgraph-view";
import {
calculateTotalTime,
convertTracesToHierarchy,
Expand Down Expand Up @@ -36,17 +37,23 @@ export const TraceRow = ({
let prompts: any = {};
let responses: any = {};
let cost = { total: 0, input: 0, output: 0 };
let langgraph = false;
for (const span of trace) {
if (span.attributes) {
const attributes = JSON.parse(span.attributes);
if (attributes["langtrace.service.name"]) {
vendor = attributes["langtrace.service.name"].toLowerCase();
if (vendor === "langgraph") {
langgraph = true;
}
}
userId = attributes["user.id"];
if (attributes["llm.prompts"] && attributes["llm.responses"]) {
prompts = attributes["llm.prompts"];
responses = attributes["llm.responses"];
}
if (attributes["llm.token.counts"]) {
model = attributes["llm.model"];
vendor = attributes["langtrace.service.name"].toLowerCase();
const currentcounts = JSON.parse(attributes["llm.token.counts"]);
tokenCounts = {
input_tokens: tokenCounts.input_tokens
Expand Down Expand Up @@ -213,6 +220,26 @@ export const TraceRow = ({
<Separator className="bg-primary h-[2px]" />
)}
</Button>
{langgraph && (
<Button
onClick={() => setSelectedTab("langgraph")}
variant={"ghost"}
className="flex flex-col justify-between pb-0"
>
<p
className={
selectedTab === "langgraph"
? "text-xs text-primary font-medium"
: "text-xs text-muted-foreground font-medium"
}
>
Langgraph
</p>
{selectedTab === "langgraph" && (
<Separator className="bg-primary h-[2px]" />
)}
</Button>
)}
</div>
<Separator />
{selectedTab === "trace" && (
Expand All @@ -235,6 +262,11 @@ export const TraceRow = ({
<LLMView prompts={prompts} responses={responses} />
</div>
)}
{selectedTab === "langgraph" && (
<div className="h-[500px]">
<LanggraphView trace={trace} />
</div>
)}
</div>
)}
</div>
Expand Down
122 changes: 122 additions & 0 deletions components/shared/langgraph-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { Span } from "@/lib/clients/scale3_clickhouse/models/span";
import ReactFlow, {
Background,
BaseEdge,
Controls,
EdgeLabelRenderer,
getBezierPath,
} from "reactflow";
import "reactflow/dist/style.css";

const CustomEdge = ({ id, data, ...props }: any) => {
const [edgePath, labelX, labelY] = getBezierPath(props);

return (
<>
<BaseEdge id={id} path={edgePath} />
<EdgeLabelRenderer>
<div
style={{
position: "absolute",
transform: `translate(-50%, -50%) translate(${labelX}px,${labelY}px)`,
background: "#000000",
padding: 1,
borderRadius: 5,
fontSize: 12,
fontWeight: 700,
color: "#ffffff",
}}
className="nodrag nopan"
>
{data.label}
</div>
</EdgeLabelRenderer>
</>
);
};

export default function LanggraphView({ trace }: { trace: Span[] }) {
// construct the nodes and edges from the trace
let x = 0;
let y = 0;
const nodes = [
{ id: "__start__", data: { label: "Start" }, position: { x: 0, y: 0 } },
];
const edges = [];
try {
for (const span of trace) {
const attributes = JSON.parse(span.attributes);
if (Object.keys(attributes).length > 0) {
const vendor = attributes["langtrace.service.name"].toLowerCase();
const node = attributes["langgraph.node"];
const edge = attributes["langgraph.edge"];
const task = attributes["langgraph.task.name"];
if (vendor === "langgraph" && node) {
x += 200;
y += 200;
const pNode = JSON.parse(node);
nodes.push({
id: pNode?.name || span.span_id,
data: {
label:
`${pNode?.name} (action: ${pNode.action})}` || span.span_id,
},
position: { x, y },
});
}

if (vendor === "langgraph" && edge) {
const pEdge = JSON.parse(edge);
if (task === "add_conditional_edges") {
const pathMap = pEdge?.path_map;
if (pathMap) {
for (const k of Object.keys(pathMap)) {
edges.push({
id: `${pEdge?.source || "source"}-${
pathMap[k] || "destination"
}`,
data: { label: `${pEdge?.path} (output: ${k})` || "" },
source: pEdge?.source || "source",
target: pathMap[k] || "destination",
type: "custom",
});
}
}
} else {
edges.push({
id: `${pEdge?.source || "source"}-${
pEdge?.destination || "destination"
}`,
source: pEdge?.source || "source",
target: pEdge?.destination || "destination",
});
}
}
}
}
} catch (e) {
console.error(e);
}

nodes.push({
id: "__end__",
data: { label: "End" },
position: { x: 0, y: y + 200 },
});

return (
<div style={{ height: "100%" }}>
<ReactFlow
nodes={nodes}
edges={edges}
edgeTypes={{
custom: CustomEdge,
}}
draggable={true}
>
<Background />
<Controls />
</ReactFlow>
</div>
);
}
48 changes: 48 additions & 0 deletions components/shared/vendor-metadata.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export function vendorBadgeColor(vendor: string) {
return "bg-red-500";
}

if (vendor.includes("qdrant")) {
return "bg-grey-500";
}

if (vendor.includes("qdrant")) {
return "bg-grey-500";
}

return "bg-gray-500";
}

Expand Down Expand Up @@ -82,6 +90,14 @@ export function vendorColor(vendor: string) {
return "bg-red-200";
}

if (vendor.includes("qdrant")) {
return "bg-grey-200";
}

if (vendor.includes("groq")) {
return "bg-slate-200";
}

return "bg-gray-800";
}

Expand Down Expand Up @@ -109,6 +125,22 @@ export function VendorLogo({
serviceName = attributes["langtrace.service.name"].toLowerCase();
}

if (span.name.includes("groq") || serviceName.includes("groq")) {
const color = vendorColor("groq");
return (
<Image
alt="Groq Logo"
src="/groq.png"
width={50}
height={50}
className={cn(
`${color} p-[3px]`,
variant === "circular" ? "rounded-full" : "rounded-md"
)}
/>
);
}

if (span.name.includes("perplexity") || serviceName.includes("perplexity")) {
const color = vendorColor("perplexity");
return (
Expand Down Expand Up @@ -237,6 +269,22 @@ export function VendorLogo({
);
}

if (span.name.includes("qdrant") || serviceName.includes("qdrant")) {
const color = vendorColor("qdrant");
return (
<Image
alt="Qdrant Logo"
src="/qdrant.png"
width={50}
height={50}
className={cn(
`${color} p-[3px]`,
variant === "circular" ? "rounded-full" : "rounded-md"
)}
/>
);
}

return (
<div className="flex items-center bg-muted p-2 rounded-sm">
<StackIcon
Expand Down
6 changes: 6 additions & 0 deletions components/traces/trace_graph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ const SpanItem: React.FC<SpanItemProps> = ({
color = "bg-indigo-500";
else if (span.name.includes("langchain") || serviceName.includes("langchain"))
color = "bg-purple-500";
else if (span.name.includes("cohere") || serviceName.includes("cohere"))
color = "bg-red-500";
else if (span.name.includes("qdrant") || serviceName.includes("qdrant"))
color = "bg-grey-500";
else if (span.name.includes("groq") || serviceName.includes("groq"))
color = "bg-slate-500";
else if (
span.name.includes("llamaindex") ||
serviceName.includes("llamaindex")
Expand Down
1 change: 0 additions & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ services:
working_dir: /app
env_file:
- .env
command: /bin/sh -c "npm run create-tables && npm run dev"
ports:
- "3000:3000"
# Uncmment this for development
Expand Down
Loading

0 comments on commit 5942844

Please sign in to comment.