Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update agent eval tutorial #582

Merged
merged 26 commits into from
Dec 19, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,217 changes: 1,802 additions & 415 deletions docs/evaluation/tutorials/agents.mdx

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/evaluation/tutorials/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ New to LangSmith or to LLM app development in general? Read this material to qui
- [Evaluate your LLM application](./tutorials/evaluation)
- [RAG Evaluations](./tutorials/rag)
- [Backtesting](./tutorials/backtesting)
- [Agent Evaluations](./tutorials/agents)
- [Evaluate an agent](./tutorials/agents)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/evaluation/tutorials/static/qa_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/evaluation/tutorials/static/refund_graph.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
75 changes: 73 additions & 2 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,82 @@ html[data-theme="dark"] {
box-shadow: none !important;
}

/* Update gutter styles */
.fold-markers {
border-right: none;
border-left: 1px solid var(--joy-palette-divider) !important;
border-top: 1px solid var(--joy-palette-divider) !important;
border-bottom: 1px solid var(--joy-palette-divider) !important;
border-radius: var(--ifm-code-border-radius) 0 0 var(--ifm-code-border-radius);
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 12px;
background: var(--prism-background-color);
z-index: 1;
}

/* Dark mode specific styling */
[data-theme='dark'] .fold-markers {
/* background: var(--prism-background-color) !important; */
background: #1e1e1e;
}

.fold-marker {
position: absolute;
cursor: pointer;
user-select: none;
color: var(--ifm-menu-color);
width: 12px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
transition: color 0.2s ease, transform 0.2s ease;
transform-origin: center;
left: 12px;
padding-top: 20px;
}
.fold-marker.collapsed {
transform: rotate(-90deg) translateX(-13px) translateY(-12px);
}
.fold-marker:hover {
color: var(--ifm-menu-color-active);
}

/* Remove border radius when inside tabs */
.tabs-container .fold-markers {
border-radius: 0 !important;
}

/* Remove code block border and shadow */
.theme-code-block {
border-color: var(--joy-palette-divider) !important;
padding-left: 0 !important;
border: 1px solid var(--joy-palette-divider) !important;
border-left: none !important;
box-shadow: var(--ifm-global-shadow-lw);
}

/* Ensure wrapper doesn't add extra shadows */
.code-block-wrapper {
box-shadow: none !important;
}

/* Remove any nested borders */
.code-block-wrapper > .code-block-with-gutter > div,
.code-block-wrapper > .code-block-with-gutter > div pre {
border-left: none !important;
border-top-left-radius: 0 !important;
border-bottom-left-radius: 0 !important;
box-shadow: none !important;
}

.code-block-with-gutter {
padding-left: 12px
}

/* Remove theme border */
.theme-code-block::before {
display: none !important;
}
Expand Down
172 changes: 168 additions & 4 deletions src/theme/CodeBlock/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable react/jsx-props-no-spreading */
import React from "react";
import React, { useState } from "react";
import CodeBlock from "@theme-original/CodeBlock";

function Imports({ imports }) {
Expand Down Expand Up @@ -33,15 +33,179 @@ function Imports({ imports }) {
);
}

function CollapsibleCodeBlock({ children, ...props }) {
const processCode = (code) => {
const lines = code.split("\n");
const processedLines = [];
let currentSection = null;

for (let i = 0; i < lines.length; i += 1) {
const line = lines[i];

// Check for region with optional [collapsed] flag
const regionMatch = line.match(
/(\/\/#region|#region)\s*(\[collapsed\])?\s*(.*)/
);
if (regionMatch) {
currentSection = {
start: i,
title: regionMatch[3].trim(),
content: [],
defaultCollapsed: !!regionMatch[2], // true if [collapsed] is present
};
} else if (line.includes("#endregion") || line.includes("//#endregion")) {
if (currentSection) {
processedLines.push({
type: "section",
...currentSection,
end: i,
});
currentSection = null;
}
} else if (currentSection) {
currentSection.content.push(line);
} else {
processedLines.push({ type: "line", content: line });
}
}

return processedLines;
};

const [collapsedSections, setCollapsedSections] = useState(() => {
const initial = new Set();
if (typeof children === "string") {
const processed = processCode(children);
processed.forEach((item, index) => {
if (item.type === "section" && item.defaultCollapsed) {
initial.add(index);
}
});
}
return initial;
});

const toggleSection = (index) => {
const newCollapsed = new Set(collapsedSections);
if (newCollapsed.has(index)) {
newCollapsed.delete(index);
} else {
newCollapsed.add(index);
}
setCollapsedSections(newCollapsed);
};

const renderCode = () => {
if (typeof children !== "string") {
return children;
}

const processedCode = processCode(children);
let result = "";

processedCode.forEach((item, index) => {
if (item.type === "line") {
result += `${item.content}\n`;
} else {
const isCollapsed = collapsedSections.has(index);
// Always show the first line
result += item.content[0] + (isCollapsed ? " ...\n" : "\n");
if (!isCollapsed) {
// Add the rest of the content starting from the second line
result +=
item.content.slice(1).join("\n") +
(index < processedCode.length - 1 ? "\n" : ""); // Only add newline if not last item
}
}
});

return result.trimEnd(); // Remove trailing whitespace and newlines
};

const getGutterItems = () => {
if (typeof children !== "string") return [];

const processedCode = processCode(children);
const items = [];
let lineCount = 0;

processedCode.forEach((item, index) => {
if (item.type === "line") {
lineCount += 1;
} else {
const isCollapsed = collapsedSections.has(index);
items.push({
line: lineCount,
title: item.title,
isCollapsed,
index,
});
// Always count the first line
lineCount += 1;
if (!isCollapsed) {
// Add the remaining lines if not collapsed
lineCount += item.content.slice(1).length;
}
}
});

return items;
};

React.useEffect(() => {
const style = document.createElement("style");
style.textContent = `
.code-block-wrapper {
position: relative;
}

`;
document.head.appendChild(style);
return () => document.head.removeChild(style);
}, []);

const gutterItems = getGutterItems();
const codeContent = renderCode();

return (
<div className="code-block-wrapper">
<div className="fold-markers">
{gutterItems.map((item) => (
<div
key={item.index}
className={`fold-marker ${item.isCollapsed ? "collapsed" : ""}`}
onClick={() => toggleSection(item.index)}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
toggleSection(item.index);
}
}}
role="button"
tabIndex={0}
style={{
top: `${item.line * 22.0375}px`,
}}
>
</div>
))}
</div>
<div className="code-block-with-gutter">
<CodeBlock {...props}>{codeContent}</CodeBlock>
</div>
</div>
);
}

export default function CodeBlockWrapper({ children, ...props }) {
if (typeof children === "string") {
return <CodeBlock {...props}>{children}</CodeBlock>;
return <CollapsibleCodeBlock {...props}>{children}</CollapsibleCodeBlock>;
}

return (
<>
<CodeBlock {...props}>{children.content}</CodeBlock>
<Imports imports={children.imports} />
<CollapsibleCodeBlock {...props}>{children.content}</CollapsibleCodeBlock>
{children.imports && <Imports imports={children.imports} />}
</>
);
}
Loading