Skip to content

Commit

Permalink
fix: Simplify the quickstart
Browse files Browse the repository at this point in the history
  • Loading branch information
nadeesha committed Dec 9, 2024
1 parent 84043d3 commit 72f9059
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 194 deletions.
58 changes: 0 additions & 58 deletions bootstrap-node/src/functions.ts

This file was deleted.

55 changes: 20 additions & 35 deletions bootstrap-node/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,54 +1,39 @@
import { Inferable } from "inferable";
import { z } from "zod";
import { execFile } from "child_process";
import { promisify } from "util";

// Some mock functions to register
import * as functions from "./functions";
const execFilePromise = promisify(execFile);

// Instantiate the Inferable client.
const client = new Inferable({
// To get a new key, run:
// npx @inferable/cli auth keys create 'My New Machine Key' --type='cluster_machine'
// Get your key from https://app.inferable.ai/clusters
apiSecret: process.env.INFERABLE_API_SECRET,
});

// Register some demo functions
client.default.register({
name: "getUrlContent",
func: functions.getUrlContent,
description: "Gets the content of a URL",
schema: {
input: z.object({
url: z.string().describe("The URL to get the content of"),
}),
},
});

client.default.register({
name: "generatePage",
func: functions.generatePage,
description: "Generates a page from markdown",
schema: {
input: z.object({
markdown: z.string().describe("The markdown to generate a page from"),
}),
name: "exec",
func: async ({ command, arg }: { command: string; arg?: string }) => {
const args = arg ? [arg] : [];
const { stdout, stderr } = await execFilePromise(command, args);
return {
stdout: stdout.trim(),
stderr: stderr.trim(),
};
},
});

client.default.register({
name: "scoreHNPost",
func: functions.scoreHNPost,
description:
"Calculates a score for a Hacker News post given its comment count and upvotes",
description: "Executes a system command",
schema: {
input: z.object({
commentCount: z.number().describe("The number of comments"),
upvotes: z.number().describe("The number of upvotes"),
command: z
.enum(["pwd", "ls", "cat", "echo"]) // This prevents arbitrary commands
.describe("The command to execute"),
arg: z
.string()
.describe("The argument to pass to the command")
.optional(),
}),
},
});

client.default.start().then(() => {
console.log("Inferable demo service started");
});

// To trigger a run: tsx -r dotenv/config src/run.ts
117 changes: 16 additions & 101 deletions bootstrap-node/src/run.ts
Original file line number Diff line number Diff line change
@@ -1,114 +1,29 @@
import { Inferable } from "inferable";
import { z } from "zod";
import { exec } from "child_process";

const client = new Inferable({
apiSecret: process.env.INFERABLE_API_SECRET,
});

const postsSchema = z.object({
id: z.string().describe("The id of the post"),
title: z.string().describe("The title of the post"),
points: z.string().describe("The key points from the comments"),
commentsUrl: z
.string()
.describe(
"The URL of the comments. This is typically https://news.ycombinator.com/item?id=<post-id>",
),
const reportSchema = z.object({
name: z.string(),
capabilities: z
.array(z.string())
.describe("The capabilities of the program. What it can do."),
});

// Trigger a Run programmatically
// https://docs.inferable.ai/pages/runs

const extract = async () =>
client
.run({
initialPrompt: `
Hacker News has a homepage at https://news.ycombinator.com/
Each post has a id, title, a link, and a score, and is voted on by users.
Score the top 10 posts and pick the top 3 according to the internal scoring function.
`,
resultSchema: z.object({
posts: postsSchema.array(),
}),
callSummarization: false,
})
.then(
(r) =>
r.poll() as Promise<{
result: {
posts?: z.infer<typeof postsSchema>[];
};
}>,
);

const summarizePost = async ({ data }: { data: object }) =>
client
.run({
initialPrompt: `
<data>
${JSON.stringify(data).substring(0, 20_000)}
</data>
You are given a post from Hacker News, and a url for the post's comments.
Summarize the comments. You should visit the comments URL to get the comments.
Produce a list of the key points from the comments.
`,
resultSchema: z.object({
id: z.string().describe("The id of the post"),
title: z.string().describe("The title of the post"),
keyPoints: z
.array(z.string())
.describe("The key points from the comments"),
}),
})
.then((r) => r.poll());

const generatePage = async ({ data }: { data: object }) =>
client
.run({
initialPrompt: `
<data>
${JSON.stringify(data)}
</data>
You are given a list of posts from Hacker News, and a summary of the comments for each post.
Generate a web page with the following structure:
- A header with the title of the page
- A list of posts, with the title, a link to the post, and the key points from the comments in a ul
- A footer with a link to the original Hacker News page
`,
resultSchema: z.object({
pagePath: z.string().describe("The path of the generated web page"),
}),
})
.then((r) => r.poll());

const url = process.env.INFERABLE_CLUSTER_ID
? `https://app.inferable.ai/clusters/${process.env.INFERABLE_CLUSTER_ID}/runs`
: "https://app.inferable.ai/clusters";

// open the page in the browser
exec(`open ${url}`, (error) => {
if (error) {
console.error("Failed to open browser:", error);
}
});

extract()
.then(({ result }) => {
if (!result.posts) {
throw new Error("No posts found");
}

return Promise.all(
result.posts.map((post) => summarizePost({ data: post })),
);
client
.run({
initialPrompt: `
Iteratively inspect the files at the current directory, and produce a report.
You may selectively inspect the contents of files.
`.trim(),
resultSchema: reportSchema,
})
.then((r) => r.poll())
.then((result) => {
return generatePage({ data: result });
console.log(result);
})
.then((result) => {
console.log("Generated page", result);
.catch((error) => {
console.error(error);
});

0 comments on commit 72f9059

Please sign in to comment.