Skip to content

Commit 54d1b39

Browse files
committed
peerbenchJS releae 0.0.16
1 parent 05da4f7 commit 54d1b39

1,896 files changed

Lines changed: 203114 additions & 12269 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

peerBenchJS/Dockerfile.webapp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
FROM node:20-bookworm AS base
2+
3+
FROM base AS deps
4+
WORKDIR /app
5+
6+
# Copy package.json files of all repos
7+
COPY package*.json .
8+
COPY apps/webapp/package*.json ./apps/webapp/
9+
COPY packages/sdk/package*.json ./packages/sdk/
10+
11+
# Install dependencies
12+
RUN npm ci
13+
14+
# Rebuild the source code only when needed
15+
FROM base AS builder
16+
WORKDIR /app
17+
COPY --from=deps /app/node_modules ./node_modules
18+
COPY --from=deps /app/apps/webapp/node_modules ./apps/webapp/node_modules
19+
COPY --from=deps /app/packages/sdk/node_modules ./packages/sdk/node_modules
20+
COPY . .
21+
22+
# Disable telemetry
23+
ENV NEXT_TELEMETRY_DISABLED=1
24+
25+
# Build the repo including webapp and sdk
26+
RUN npm run build
27+
28+
# Production image, copy all the files and run next
29+
FROM base AS runner
30+
WORKDIR /app
31+
32+
ENV NODE_ENV=production
33+
ENV NEXT_TELEMETRY_DISABLED=1
34+
35+
RUN addgroup --system --gid 1001 nodejs
36+
RUN adduser --system --uid 1001 nextjs
37+
38+
COPY --from=builder /app/apps/webapp/public ./public
39+
40+
COPY --from=builder --chown=nextjs:nodejs /app/apps/webapp/.next/standalone ./
41+
COPY --from=builder --chown=nextjs:nodejs /app/apps/webapp/.next/static ./.next/static
42+
43+
USER nextjs
44+
45+
EXPOSE 3000
46+
47+
ENV PORT=3000
48+
ENV HOSTNAME="0.0.0.0"
49+
50+
CMD ["node", "apps/webapp/server.js"]

peerBenchJS/README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11

22

3-
43
# The problem:
54

6-
Public benchmark test data sets make AI model performance comparable. But this creates an incentivization for closed source models to cheat the benchmarks by training on test data or creating heuristics that overfit the benchmark test dataset .....
5+
Public benchmark test data sets make AI model performance comparable. But this creates an incentivization for closed source models to cheat the benchmarks by training on test data or creating heuristics that overfit the benchmark test dataset .
76

87
# Our solution:
98

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {
2+
AbstractCollector,
3+
PubMedCollector,
4+
StringCollector,
5+
} from "@peerbench/sdk";
6+
7+
export const collectors: AbstractCollector<unknown>[] = [
8+
new StringCollector(),
9+
new PubMedCollector(),
10+
// TODO: Add more Collectors if there are anymore
11+
];
12+
13+
/**
14+
* Gets a Collector by its identifier from the given list of Collectors
15+
*/
16+
export function getCollector(identifier: string) {
17+
return collectors.find((c) => c.identifier === identifier);
18+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { program } from "@/core/program";
2+
import { getCollector } from "@/collectors";
3+
import { AbstractCollector } from "@peerbench/sdk";
4+
import { saveCollectedData } from "./save-collected-data";
5+
import { logger } from "@/core/logger";
6+
import { hashFile } from "@/utils/hash-file";
7+
import { signFile } from "@/utils/sign-file";
8+
import { FileSchema } from "@/validation/file-schema";
9+
import { JSONSchema } from "@/validation/json-schema";
10+
import { z } from "zod";
11+
import fs from "fs/promises";
12+
13+
export const collectCommand = program
14+
.command("collect")
15+
.description("Collects raw data")
16+
.requiredOption(
17+
"-s, --source <sources...>",
18+
"Source inputs for the Collector"
19+
)
20+
.requiredOption(
21+
"-o, --output <output>",
22+
"Output directory",
23+
"peerbench-data/collected"
24+
)
25+
.requiredOption(
26+
"-c, --collector <collector>",
27+
"Collector identifier",
28+
(value) => {
29+
const collector = getCollector(value);
30+
if (!collector) {
31+
throw new Error(`Collector "${value}" not found`);
32+
}
33+
return collector;
34+
}
35+
)
36+
.option(
37+
"--options <path or JSON string>",
38+
"Path to the options file or a JSON string that will be passed to the Collector",
39+
(value) =>
40+
z
41+
.union([
42+
JSONSchema<any>(),
43+
FileSchema().pipe(
44+
JSONSchema({
45+
message: "Given options file is not a valid JSON file",
46+
})
47+
),
48+
])
49+
.parse(value)
50+
)
51+
.option(
52+
"--args <path or JSON string>",
53+
"Path to the initialization args file or a JSON string that will be passed to the Collector",
54+
(value) =>
55+
z
56+
.union([
57+
JSONSchema<any>(),
58+
FileSchema().pipe(
59+
JSONSchema({ message: "Given args file is not a valid JSON file" })
60+
),
61+
])
62+
.parse(value)
63+
)
64+
.option("-t, --tag <tags...>", "Tags to be attached to the output file")
65+
.action(
66+
async (options: {
67+
source: string[];
68+
collector: AbstractCollector<unknown>;
69+
output: string;
70+
tag: string[];
71+
options: any;
72+
args: any;
73+
}) => {
74+
// Ensure the output directory exists
75+
await fs.mkdir(options.output, { recursive: true });
76+
77+
const tags = options.tag;
78+
79+
// Initialize the Collector
80+
await options.collector.initialize(options.args);
81+
82+
for (const source of options.source) {
83+
logger.info(
84+
`Collecting data from ${source} using ${options.collector.identifier}`
85+
);
86+
87+
const collectedData = await options.collector
88+
.collect(source, options.options)
89+
.catch((err) => {
90+
logger.error(
91+
`Error collecting data from ${source} using ${options.collector.identifier}: ${err}`
92+
);
93+
94+
return undefined;
95+
});
96+
97+
// Collected data will be undefined if
98+
// the Collector failed to collect the data
99+
if (!collectedData) {
100+
throw new Error("Failed to collect data");
101+
}
102+
103+
// Save the data
104+
const filePath = await saveCollectedData({
105+
outputDirectory: options.output,
106+
collectorIdentifier: options.collector.identifier,
107+
source,
108+
collectedData,
109+
tags,
110+
});
111+
112+
// Hash and sign the output file
113+
await hashFile(filePath);
114+
await signFile(`${filePath}.cid`); // Only sign the hash file
115+
116+
logger.info(`Data saved to: ${filePath}`);
117+
}
118+
}
119+
);
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { dateString } from "@/utils/date-string";
2+
import { normalizePath } from "@/utils/normalize-path";
3+
import { CollectedDataSave } from "@/validation/collected-data-schema";
4+
import fs from "fs/promises";
5+
import path from "path";
6+
7+
/**
8+
* Saves the data that was collected by a Collector to a file in JSON format
9+
*
10+
* @returns The path to the saved file
11+
*/
12+
export async function saveCollectedData(params: {
13+
source: unknown;
14+
outputDirectory: string;
15+
collectorIdentifier: string;
16+
collectedData: any;
17+
tags?: string[];
18+
}) {
19+
const tags =
20+
params.tags && params.tags.length > 0 ? `.${params.tags.join("-")}` : "";
21+
const timestamp = dateString();
22+
const fileName = normalizePath(
23+
`${params.collectorIdentifier}.${timestamp}.collected${tags}.json`
24+
);
25+
const filePath = path.join(params.outputDirectory, fileName);
26+
const fileContent: CollectedDataSave = {
27+
collectorIdentifier: params.collectorIdentifier,
28+
source: params.source,
29+
data: params.collectedData,
30+
};
31+
32+
await fs.writeFile(filePath, JSON.stringify(fileContent, null, 2), "utf-8");
33+
34+
return filePath;
35+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
import { logger } from "@/core/logger";
2+
import { program } from "@/core/program";
3+
import { getGenerator } from "@/generators";
4+
import {
5+
CollectedDataSave,
6+
CollectedDataSchema,
7+
} from "@/validation/collected-data-schema";
8+
import { FileSchema } from "@/validation/file-schema";
9+
import { JSONSchema } from "@/validation/json-schema";
10+
import { AbstractGenerator } from "@peerbench/sdk";
11+
import { z } from "zod";
12+
import { savePrompts } from "./save-prompts";
13+
import { hashFile } from "@/utils/hash-file";
14+
import { signFile } from "@/utils/sign-file";
15+
import { OptionOutputDir } from "../options/output-dir";
16+
import { OptionTags } from "../options/tags";
17+
import fs from "fs/promises";
18+
19+
program
20+
.command("generate")
21+
.description("Generates new Prompts")
22+
.requiredOption(
23+
"-g, --generator <identifier>",
24+
"Identifier of the Generator",
25+
(value) => {
26+
const generator = getGenerator(value);
27+
if (!generator) {
28+
throw new Error(`Generator "${value}" not found`);
29+
}
30+
return generator;
31+
}
32+
)
33+
.requiredOption(
34+
"-f, --file <path>",
35+
"Path to the collected data file",
36+
(value) =>
37+
FileSchema({ message: "Data file doesn't exist" })
38+
.pipe(
39+
JSONSchema({
40+
message: "Given data file is invalid",
41+
schema: CollectedDataSchema,
42+
})
43+
)
44+
.parse(value)
45+
)
46+
.addOption(OptionOutputDir("generated").makeOptionMandatory(true))
47+
.option(
48+
"--options <path or JSON string>",
49+
"Path to the options file or a JSON string that will be passed to the Generator",
50+
(value) =>
51+
z
52+
.union([
53+
JSONSchema<any>(),
54+
FileSchema().pipe(
55+
JSONSchema({
56+
message: "Given options file is invalid",
57+
schema: z.record(z.string(), z.unknown()),
58+
})
59+
),
60+
])
61+
.parse(value)
62+
)
63+
.option(
64+
"--args <path or JSON string>",
65+
"Path to the initialization args file or a JSON string that will be passed to the Generator",
66+
(value) =>
67+
z
68+
.union([
69+
JSONSchema<any>(),
70+
FileSchema().pipe(
71+
JSONSchema({
72+
message: "Given args file is invalid",
73+
schema: z.array(z.unknown()),
74+
})
75+
),
76+
])
77+
.parse(value)
78+
)
79+
.addOption(OptionTags())
80+
.action(
81+
async (options: {
82+
generator: AbstractGenerator;
83+
file: CollectedDataSave;
84+
tags: string[];
85+
options: Record<string, unknown>;
86+
args: unknown[];
87+
output: string;
88+
}) => {
89+
// Ensure the output directory exists
90+
await fs.mkdir(options.output, { recursive: true });
91+
92+
logger.info("Initializing Generator");
93+
94+
// Initialize the Generator
95+
await options.generator.initialize(options.args);
96+
97+
logger.info(`Checking the Generator eligibility for the given file`);
98+
const canHandle = await options.generator.canHandle(options.file);
99+
if (!canHandle) {
100+
throw new Error("Generator doesn't support the given file");
101+
}
102+
103+
logger.info(`Generating Prompts`);
104+
const prompts = await options.generator.generate(
105+
options.file.data,
106+
options.options
107+
);
108+
logger.info(`Prompts generated successfully`);
109+
110+
logger.info(`Saving Prompts`);
111+
// Save the data
112+
const filePath = await savePrompts({
113+
generatorIdentifier: options.generator.identifier,
114+
outputDirectory: options.output,
115+
prompts,
116+
tags: options.tags,
117+
});
118+
119+
// Hash and sign the output file
120+
await hashFile(filePath);
121+
await signFile(`${filePath}.cid`); // Only sign the hash file
122+
123+
logger.info(`Prompts saved to: ${filePath}`);
124+
}
125+
);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Prompt } from "@peerbench/sdk";
2+
import path from "path";
3+
import fs from "fs/promises";
4+
import { dateString } from "@/utils/date-string";
5+
import { normalizePath } from "@/utils/normalize-path";
6+
7+
/**
8+
* Saves the Prompts to a file in peerBench Task format
9+
*
10+
* @returns The path to the saved file
11+
*/
12+
export async function savePrompts(params: {
13+
generatorIdentifier: string;
14+
outputDirectory: string;
15+
prompts: Prompt[];
16+
tags?: string[];
17+
}) {
18+
const tags =
19+
params.tags && params.tags.length > 0 ? `.${params.tags.join("-")}` : "";
20+
const timestamp = dateString();
21+
const fileName = normalizePath(
22+
`${params.generatorIdentifier}.${timestamp}.generated${tags}.json`
23+
);
24+
const filePath = path.join(params.outputDirectory, fileName);
25+
26+
await fs.writeFile(filePath, JSON.stringify(params.prompts));
27+
28+
return filePath;
29+
}

0 commit comments

Comments
 (0)