Skip to content

Commit

Permalink
More flexible generateJson prompt.
Browse files Browse the repository at this point in the history
  • Loading branch information
lgrammel committed Jul 15, 2023
1 parent 1c06afa commit dc0ddb7
Show file tree
Hide file tree
Showing 12 changed files with 233 additions and 181 deletions.
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,20 @@ for await (const textFragment of textStream) {
```ts
const json = await generateJson(
new OpenAIChatModel({ model: "gpt-3.5-turbo", maxTokens: 1000 }),
[
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user("A robot learning to love"),
],
{
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
}
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user("A robot learning to love"),
],
fn: {
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
},
})
);
```

Expand Down
60 changes: 33 additions & 27 deletions docs/concept/function/generate-json.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,29 @@ Generates JSON using a prompt and a structure.

[generateJson API](/api/modules#generatejson)

Generates JSON using a prompt and a structure.
Generates JSON using a prompt.
The prompt format depends on the model.
The structure is a JSON object that describes the desired output.
The parameters must be a Zod object schema.
It contains the information required to parse the generated JSON.

#### With OpenAI chat model

```ts
const story = await generateJson(
new OpenAIChatModel(/* ... */),
[
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user("A robot learning to love"),
],
{
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
}
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user("A robot learning to love"),
],
fn: {
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
},
})
);
```

Expand All @@ -50,18 +51,23 @@ The input signature of the prompt templates becomes the call signature of the ge
```ts
const generateStoryAbout = generateJsonAsFunction(
new OpenAITextGenerationModel(/* ... */),
async (theme: string) => [
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user(theme),
],
{
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
}
async (theme: string) =>
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system(
"You are a story writer. Write a story about:"
),
OpenAIChatMessage.user(theme),
],
fn: {
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
},
})
);

const story = await generateStoryAbout("A robot learning to love");
Expand Down
40 changes: 22 additions & 18 deletions docs/integration/model-provider/openai.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,32 @@ for await (const textFragment of textStream) {
JSON generation uses the [OpenAI GPT function calling API](https://platform.openai.com/docs/guides/gpt/function-calling). It provides a single function specification and instructs the model to provide parameters for calling the function. The result is returned as parsed JSON.

[OpenAIChatModel API](/api/classes/OpenAIChatModel)
[OpenAIChatSingleFunctionPrompt API](/api/classes/OpenAIChatSingleFunctionPrompt)

```ts
import { OpenAIChatMessage, OpenAIChatModel, generateJson } from "ai-utils.js";
import {
OpenAIChatMessage,
OpenAIChatModel,
OpenAIChatSingleFunctionPrompt,
generateJson,
} from "ai-utils.js";

const json = await generateJson(
new OpenAIChatModel({
model: "gpt-3.5-turbo",
temperature: 0.7,
maxTokens: 1000,
}),
[
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user("A robot learning to love"),
],
{
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
}
new OpenAIChatModel({ model: "gpt-3.5-turbo", maxTokens: 1000 }),
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user("A robot learning to love"),
],
fn: {
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
},
})
);
```

Expand Down
41 changes: 22 additions & 19 deletions docs/recipe/sentiment-analysis.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,28 @@ const analyzeSentiment = generateJsonAsFunction(
temperature: 0, // remove randomness
maxTokens: 500, // enough tokens for reasoning and sentiment
}),
async (productReview: string) => [
OpenAIChatMessage.system(
"You are a sentiment evaluator. " +
"Analyze the sentiment of the following product review:"
),
OpenAIChatMessage.user(productReview),
],
{
name: "sentiment",
description: "Write the sentiment analysis",
parameters: z.object({
// Reason first to improve results:
reasoning: z.string().describe("Reasoning to explain the sentiment."),
// Report sentiment after reasoning:
sentiment: z
.enum(["positive", "neutral", "negative"])
.describe("Sentiment."),
}),
}
async (productReview: string) =>
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system(
"You are a sentiment evaluator. " +
"Analyze the sentiment of the following product review:"
),
OpenAIChatMessage.user(productReview),
],
fn: {
name: "sentiment",
description: "Write the sentiment analysis",
parameters: z.object({
// Reason first to improve results:
reasoning: z.string().describe("Reasoning to explain the sentiment."),
// Report sentiment after reasoning:
sentiment: z
.enum(["positive", "neutral", "negative"])
.describe("Sentiment."),
}),
},
})
);
```

Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import { OpenAIChatMessage, OpenAIChatModel, generateJson } from "ai-utils.js";
import {
OpenAIChatMessage,
OpenAIChatModel,
OpenAIChatSingleFunctionPrompt,
generateJson,
} from "ai-utils.js";
import dotenv from "dotenv";
import { z } from "zod";

dotenv.config();

(async () => {
const json = await generateJson(
new OpenAIChatModel({
model: "gpt-3.5-turbo",
temperature: 0.7,
maxTokens: 1000,
}),
[
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user("A robot learning to love"),
],
{
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
}
new OpenAIChatModel({ model: "gpt-3.5-turbo", maxTokens: 1000 }),
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system(
"You are a story writer. Write a story about:"
),
OpenAIChatMessage.user("A robot learning to love"),
],
fn: {
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
},
})
);

console.log(JSON.stringify(json, null, 2));
Expand Down
43 changes: 25 additions & 18 deletions examples/basic/src/recipes/sentiment-analysis.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
OpenAIChatMessage,
OpenAIChatModel,
OpenAIChatSingleFunctionPrompt,
generateJsonAsFunction,
} from "ai-utils.js";
import dotenv from "dotenv";
Expand All @@ -15,24 +16,30 @@ dotenv.config();
temperature: 0, // remove randomness
maxTokens: 500, // enough tokens for reasoning and sentiment
}),
async (productReview: string) => [
OpenAIChatMessage.system(
"You are a sentiment evaluator. Analyze the sentiment of the following product review:"
),
OpenAIChatMessage.user(productReview),
],
{
name: "sentiment",
description: "Write the sentiment analysis",
parameters: z.object({
// Reason first to improve results:
reasoning: z.string().describe("Reasoning to explain the sentiment."),
// Report sentiment after reasoning:
sentiment: z
.enum(["positive", "neutral", "negative"])
.describe("Sentiment."),
}),
}
async (productReview: string) =>
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system(
"You are a sentiment evaluator. " +
"Analyze the sentiment of the following product review:"
),
OpenAIChatMessage.user(productReview),
],
fn: {
name: "sentiment",
description: "Write the sentiment analysis",
parameters: z.object({
// Reason first to improve results:
reasoning: z
.string()
.describe("Reasoning to explain the sentiment."),
// Report sentiment after reasoning:
sentiment: z
.enum(["positive", "neutral", "negative"])
.describe("Sentiment."),
}),
},
})
);

const result1 = await analyzeSentiment(
Expand Down
30 changes: 18 additions & 12 deletions examples/basic/src/text/generate-json-as-function-example.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
OpenAIChatMessage,
OpenAIChatModel,
OpenAIChatSingleFunctionPrompt,
generateJsonAsFunction,
} from "ai-utils.js";
import dotenv from "dotenv";
Expand All @@ -15,18 +16,23 @@ dotenv.config();
temperature: 0.7,
maxTokens: 1000,
}),
async (theme: string) => [
OpenAIChatMessage.system("You are a story writer. Write a story about:"),
OpenAIChatMessage.user(theme),
],
{
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
}
async (theme: string) =>
new OpenAIChatSingleFunctionPrompt({
messages: [
OpenAIChatMessage.system(
"You are a story writer. Write a story about:"
),
OpenAIChatMessage.user(theme),
],
fn: {
name: "story",
description: "Write the story",
parameters: z.object({
title: z.string().describe("The title of the story"),
content: z.string().describe("The content of the story"),
}),
},
})
);

const story = await generateStoryAbout("A robot learning to love");
Expand Down
Loading

1 comment on commit dc0ddb7

@vercel
Copy link

@vercel vercel bot commented on dc0ddb7 Jul 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

ai-utils-js – ./

ai-utils-js-git-main-lgrammel.vercel.app
ai-utils.vercel.app
ai-utils-js-lgrammel.vercel.app
ai-utils.dev

Please sign in to comment.