-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3439 from quantified-uncertainty/ai-evals
AI analytics - first iteration
- Loading branch information
Showing
18 changed files
with
3,522 additions
and
664 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
const esbuild = require("esbuild"); | ||
|
||
for (const name of [ | ||
"buildRecentModelRevision/worker", | ||
"buildRecentModelRevision/main", | ||
"print-schema", | ||
]) { | ||
esbuild.buildSync({ | ||
entryPoints: [`./src/scripts/${name}.ts`], | ||
platform: "node", | ||
format: "esm", | ||
sourcemap: true, | ||
minify: true, | ||
bundle: true, | ||
// via https://github.com/evanw/esbuild/pull/2067#issuecomment-1073039746 | ||
banner: { | ||
js: ` | ||
await (async () => { | ||
const { dirname } = await import("path"); | ||
const { fileURLToPath } = await import("url"); | ||
/** | ||
* Shim entry-point related paths. | ||
*/ | ||
if (typeof globalThis.__filename === "undefined") { | ||
globalThis.__filename = fileURLToPath(import.meta.url); | ||
} | ||
if (typeof globalThis.__dirname === "undefined") { | ||
globalThis.__dirname = dirname(globalThis.__filename); | ||
} | ||
/** | ||
* Shim require if needed. | ||
*/ | ||
if (typeof globalThis.require === "undefined") { | ||
const { default: module } = await import("module"); | ||
globalThis.require = module.createRequire(import.meta.url); | ||
} | ||
})(); | ||
`, | ||
}, | ||
outfile: `./dist/scripts/${name}.mjs`, | ||
external: ["server-only"], | ||
}); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
"use client"; | ||
import { PropsWithChildren } from "react"; | ||
|
||
import { NarrowPageLayout } from "@/components/layout/NarrowPageLayout"; | ||
import { StyledTabLink } from "@/components/ui/StyledTabLink"; | ||
|
||
// workaround for https://github.com/vercel/next.js/issues/58776 - StyledTabLink won't work in server components | ||
export const AiAnalyticsClientLayout = ({ children }: PropsWithChildren) => { | ||
return ( | ||
<NarrowPageLayout> | ||
<div className="mb-4 flex items-center gap-2"> | ||
<StyledTabLink.List> | ||
<StyledTabLink name="Statistics" href="/ai/analytics" /> | ||
<StyledTabLink name="Code Errors" href="/ai/analytics/code-errors" /> | ||
<StyledTabLink name="Step Errors" href="/ai/analytics/step-errors" /> | ||
</StyledTabLink.List> | ||
</div> | ||
<div>{children}</div> | ||
</NarrowPageLayout> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { FC, Fragment } from "react"; | ||
|
||
import { H2 } from "@/components/ui/Headers"; | ||
import { type StepError } from "@/server/ai/analytics"; | ||
|
||
export const StepErrorList: FC<{ | ||
errors: StepError[]; | ||
title: string; | ||
stats?: Record<string, number>; | ||
}> = ({ errors, title, stats = {} }) => { | ||
return ( | ||
<div> | ||
<H2>{title}</H2> | ||
<strong>Total: {errors.length}</strong> | ||
<div className="my-4 grid grid-cols-2 gap-x-4"> | ||
{Object.entries(stats).map(([type, count]) => ( | ||
<Fragment key={type}> | ||
<div>{type}</div> | ||
<strong>{count}</strong> | ||
</Fragment> | ||
))} | ||
</div> | ||
<div className="space-y-4"> | ||
{errors.map((error, i) => ( | ||
<div key={i}> | ||
<div className="text-sm"> | ||
<strong>{error.stepName}</strong>{" "} | ||
<span className="text-gray-500"> | ||
({error.date.toISOString()}) | ||
</span> | ||
</div> | ||
<pre key={i} className="whitespace-pre-wrap text-xs"> | ||
{error.error} | ||
</pre> | ||
</div> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { getCodeErrors } from "@/server/ai/analytics"; | ||
|
||
import { StepErrorList } from "../StepErrorList"; | ||
|
||
const commonErrorTypes = { | ||
"sTest is not defined": "sTest import", | ||
'The "to" function only accepts paramaters above 0': | ||
"`A to B` with nonpositive args", | ||
}; | ||
|
||
const SYNTAX_ERROR = "Syntax errors"; | ||
const SIGNATURE_ERROR = "Signature errors (total)"; | ||
const LONG_ERROR = "Long errors"; | ||
const NOT_DEFINED_ERROR = "Undefined variable"; | ||
|
||
export default async function ({ | ||
searchParams, | ||
}: { | ||
searchParams: { [key: string]: string | string[] | undefined }; | ||
}) { | ||
const errors = await getCodeErrors(); | ||
|
||
// pre-initialized to follow the right key order | ||
const stats: Record<string, number> = Object.fromEntries( | ||
Object.entries(commonErrorTypes).map(([, name]) => [name, 0]) | ||
); | ||
|
||
const inc = (key: string) => (stats[key] = (stats[key] ?? 0) + 1); | ||
|
||
stats[SYNTAX_ERROR] = 0; | ||
stats[LONG_ERROR] = 0; | ||
stats[NOT_DEFINED_ERROR] = 0; | ||
stats[SIGNATURE_ERROR] = 0; | ||
|
||
for (const error of errors) { | ||
for (const [template, errorName] of Object.entries(commonErrorTypes)) { | ||
if (error.error.includes(template)) { | ||
inc(errorName); | ||
} | ||
} | ||
|
||
{ | ||
const match = error.error.match( | ||
/^Error: There are function matches for (\w+)\(/ | ||
); | ||
if (match) { | ||
inc(SIGNATURE_ERROR); | ||
inc(`${match[1]} signature`); | ||
} | ||
} | ||
|
||
if (error.error.length > 3000) { | ||
inc(LONG_ERROR); | ||
} | ||
|
||
if (error.error.startsWith('Expected "')) { | ||
inc(SYNTAX_ERROR); | ||
} | ||
|
||
if ( | ||
error.error.match(/^\S+ is not defined/) && | ||
!error.error.startsWith("sTest ") | ||
) { | ||
inc(NOT_DEFINED_ERROR); | ||
} | ||
} | ||
|
||
return <StepErrorList errors={errors} title="Code errors" stats={stats} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { PropsWithChildren } from "react"; | ||
|
||
import { checkRootUser } from "@/server/helpers"; | ||
|
||
import { AiAnalyticsClientLayout } from "./ClientLayout"; | ||
|
||
export default async function ({ children }: PropsWithChildren) { | ||
await checkRootUser(); | ||
return <AiAnalyticsClientLayout>{children}</AiAnalyticsClientLayout>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { Fragment } from "react"; | ||
|
||
import { H2 } from "@/components/ui/Headers"; | ||
import { getTypeStats } from "@/server/ai/analytics"; | ||
|
||
export default async function () { | ||
const typeStats = await getTypeStats(); | ||
return ( | ||
<div className="space-y-4"> | ||
{Object.entries(typeStats).map(([stepName, typeCounts]) => ( | ||
<div key={stepName} className="grid grid-cols-2 gap-4"> | ||
<div className="col-span-2"> | ||
<H2>{stepName}</H2> | ||
</div> | ||
{Object.entries(typeCounts).map(([type, count]) => ( | ||
<Fragment key={type}> | ||
<span>{type}</span> | ||
<span>{count}</span> | ||
</Fragment> | ||
))} | ||
</div> | ||
))} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { getStepErrors } from "@/server/ai/analytics"; | ||
|
||
import { StepErrorList } from "../StepErrorList"; | ||
|
||
export default async function () { | ||
const errors = await getStepErrors(); | ||
|
||
const stats: Record<string, number> = {}; | ||
stats["rate_limit"] = errors.filter((e) => | ||
e.error.includes("rate limit") | ||
).length; | ||
stats["price_limit"] = errors.filter((e) => | ||
e.error.includes("Price limit") | ||
).length; | ||
stats["search_and_replace"] = errors.filter((e) => | ||
e.error.includes("Search and Replace Failed") | ||
).length; | ||
|
||
return <StepErrorList errors={errors} title="Step errors" stats={stats} />; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
"use client"; | ||
import { usePathname } from "next/navigation"; | ||
import React, { FC, ReactNode } from "react"; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.