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

Feat summarize audio topic #594

Merged
merged 4 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
25 changes: 5 additions & 20 deletions enjoy/src/commands/analyze.command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { textCommand } from "./text.command";

export const analyzeCommand = async (
text: string,
Expand All @@ -10,29 +10,14 @@ export const analyzeCommand = async (
baseUrl?: string;
}
): Promise<string> => {
const { key, temperature = 0, baseUrl } = options;
let { modelName = "gpt-4-turbo" } = options;
if (!text) throw new Error("Text is required");

const chatModel = new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature,
configuration: {
baseURL: baseUrl,
},
cache: false,
verbose: true,
maxRetries: 2,
});

const prompt = ChatPromptTemplate.fromMessages([
const prompt = await ChatPromptTemplate.fromMessages([
["system", SYSTEM_PROMPT],
["human", text],
]);

const response = await prompt.pipe(chatModel).invoke({});
]).format({});

return response.text;
return textCommand(prompt, options);
};

const SYSTEM_PROMPT = `你是我的英语教练,我将提供英语文本,你将帮助我分析文本的句子结构、语法和词汇/短语,并对文本进行详细解释。请用中文回答,并按以下格式返回结果:
Expand Down
62 changes: 13 additions & 49 deletions enjoy/src/commands/extract-story.command.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,37 @@
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { zodToJsonSchema } from "zod-to-json-schema";
import { z } from "zod";
import { RESPONSE_JSON_FORMAT_MODELS } from "@/constants";
import { jsonCommand } from "./json.command";

export const extractStoryCommand = async (
content: string,
text: string,
options: {
key: string;
modelName?: string;
temperature?: number;
baseUrl?: string;
}
): Promise<{ words: string[]; idioms: string[] }> => {
const { key, temperature = 0, baseUrl } = options;
let { modelName = "gpt-4-turbo" } = options;

if (RESPONSE_JSON_FORMAT_MODELS.indexOf(modelName) === -1) {
modelName = "gpt-4-turbo";
}

const saveExtraction = z.object({
const schema = z.object({
words: z.array(z.string().describe("extracted word")),
idioms: z.array(z.string().describe("extracted idiom")),
});

const chatModel = new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature,
modelKwargs: {
response_format: {
type: "json_object",
},
},
configuration: {
baseURL: baseUrl,
},
cache: true,
verbose: true,
maxRetries: 2,
}).bind({
tools: [
{
type: "function",
function: {
name: "save_extraction",
description: "Save the extracted words and idioms from a text",
parameters: zodToJsonSchema(saveExtraction),
},
},
],
});

const prompt = ChatPromptTemplate.fromMessages([
const prompt = await ChatPromptTemplate.fromMessages([
["system", EXTRACT_STORY_PROMPT],
["human", "{text}"],
]);

const response = await prompt.pipe(chatModel).invoke({
]).format({
learning_language: "English",
text: content,
text,
});

return JSON.parse(
response.additional_kwargs?.tool_calls?.[0]?.function?.arguments || "{}"
);
return jsonCommand(prompt, { ...options, schema });
};

const EXTRACT_STORY_PROMPT = `
I am an {learning_language} beginner and only have a grasp of 500 high-frequency basic words. You are an {learning_language} learning assistant robot, and your task is to analyze the article I provide and extract all the meaningful words and idioms that I may not be familiar with. Specifically, it should include common words used in uncommon ways. Return in JSON format.
I am an {learning_language} beginner and only have a grasp of 500 high-frequency basic words. You are an {learning_language} learning assistant robot, and your task is to analyze the article I provide and extract all the meaningful words and idioms that I may not be familiar with. Specifically, it should include common words used in uncommon ways. Return in JSON format like following:

{{
words: ["word1", "word2", ...],
idiom: ["idiom1", "idiom2", ...]
}}
`;
3 changes: 3 additions & 0 deletions enjoy/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ export * from "./extract-story.command";
export * from "./lookup.command";
export * from "./translate.command";
export * from "./ipa.command";
export * from "./json.command";
export * from "./analyze.command";
export * from "./punctuate.command";
export * from "./summarize-topic.command";
export * from "./text.command";
58 changes: 6 additions & 52 deletions enjoy/src/commands/ipa.command.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { z } from "zod";
import {
StructuredOutputParser,
OutputFixingParser,
} from "langchain/output_parsers";
import { RESPONSE_JSON_FORMAT_MODELS } from "@/constants";
import { jsonCommand } from "./json.command";

export const ipaCommand = async (
text: string,
Expand All @@ -16,14 +11,9 @@ export const ipaCommand = async (
baseUrl?: string;
}
): Promise<{ words?: { word?: string; ipa?: string }[] }> => {
const { key, temperature = 0, baseUrl } = options;
let { modelName = "gpt-4-turbo" } = options;
if (!text) throw new Error("Text is required");

if (RESPONSE_JSON_FORMAT_MODELS.indexOf(modelName) === -1) {
modelName = "gpt-4-turbo";
}

const responseSchema = z.object({
const schema = z.object({
words: z.array(
z.object({
word: z.string().nonempty(),
Expand All @@ -32,51 +22,15 @@ export const ipaCommand = async (
),
});

const parser = StructuredOutputParser.fromZodSchema(responseSchema);
const fixParser = OutputFixingParser.fromLLM(
new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature: 0,
configuration: {
baseURL: baseUrl,
},
}),
parser
);

const chatModel = new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature,
configuration: {
baseURL: baseUrl,
},
modelKwargs: {
response_format: {
type: "json_object",
},
},
cache: true,
verbose: true,
maxRetries: 2,
});

const prompt = ChatPromptTemplate.fromMessages([
const prompt = await ChatPromptTemplate.fromMessages([
["system", SYSTEM_PROMPT],
["human", "{text}"],
]);

const response = await prompt.pipe(chatModel).invoke({
]).format({
learning_language: "English",
text,
});

try {
return await parser.parse(response.text);
} catch (e) {
return await fixParser.parse(response.text);
}
return jsonCommand(prompt, { ...options, schema });
};

const SYSTEM_PROMPT = `Generate an array of JSON objects for each {learning_language} word in the given text, with each object containing two keys: 'word' and 'ipa', where 'ipa' is the International Phonetic Alphabet (IPA) representation of the word. Return the array in JSON format only. The output should be structured like this:
Expand Down
48 changes: 48 additions & 0 deletions enjoy/src/commands/json.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ChatOpenAI } from "@langchain/openai";
import { RESPONSE_JSON_FORMAT_MODELS } from "@/constants";
import { zodToJsonSchema } from "zod-to-json-schema";

export const jsonCommand = async (
prompt: string,
options: {
key: string;
modelName?: string;
temperature?: number;
baseUrl?: string;
schema: any;
}
): Promise<any> => {
const { key, temperature = 0, baseUrl, schema } = options;
let { modelName = "gpt-4-turbo" } = options;

if (RESPONSE_JSON_FORMAT_MODELS.indexOf(modelName) === -1) {
modelName = "gpt-4-turbo";
}

const chatModel = new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature,
modelKwargs: {
response_format: {
type: "json_object",
},
},
configuration: {
baseURL: baseUrl,
},
cache: true,
verbose: true,
maxRetries: 1,
});

const structuredOutput = chatModel.withStructuredOutput(
zodToJsonSchema(schema),
{
method: "jsonMode",
}
);

const response = await structuredOutput.invoke(prompt);
return response;
};
53 changes: 5 additions & 48 deletions enjoy/src/commands/lookup.command.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { z } from "zod";
import {
StructuredOutputParser,
OutputFixingParser,
} from "langchain/output_parsers";
import { RESPONSE_JSON_FORMAT_MODELS } from "@/constants";
import { jsonCommand } from "./json.command";

export const lookupCommand = async (
params: {
Expand All @@ -29,16 +24,9 @@ export const lookupCommand = async (
translation?: string;
lemma?: string;
}> => {
const { key, temperature = 0, baseUrl } = options;
let { modelName = "gpt-4-turbo" } = options;

if (RESPONSE_JSON_FORMAT_MODELS.indexOf(modelName) === -1) {
modelName = "gpt-4-turbo";
}

const { word, context, meaningOptions } = params;

const responseSchema = z.object({
const schema = z.object({
id: z.string().optional(),
word: z.string().optional(),
context_translation: z.string().optional(),
Expand All @@ -49,37 +37,10 @@ export const lookupCommand = async (
lemma: z.string().optional(),
});

const parser = StructuredOutputParser.fromZodSchema(responseSchema);
const fixParser = OutputFixingParser.fromLLM(
new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature: 0,
configuration: {
baseURL: baseUrl,
},
}),
parser
);

const chatModel = new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature,
configuration: {
baseURL: baseUrl,
},
cache: true,
verbose: true,
maxRetries: 2,
});

const prompt = ChatPromptTemplate.fromMessages([
const prompt = await ChatPromptTemplate.fromMessages([
["system", DICITIONARY_PROMPT],
["human", "{input}"],
]);

const response = await prompt.pipe(chatModel).invoke({
]).format({
learning_language: "English",
native_language: "Chinese",
input: JSON.stringify({
Expand All @@ -89,11 +50,7 @@ export const lookupCommand = async (
}),
});

try {
return await parser.parse(response.text);
} catch (e) {
return await fixParser.parse(response.text);
}
return jsonCommand(prompt, { ...options, schema });
};

const DICITIONARY_PROMPT = `You are an {learning_language}-{native_language} dictionary. I will provide "word(it also maybe a phrase)" and "context" as input, you should return the "word", "lemma", "pronunciation", "pos(part of speech, maybe empty for phrase)", "definition", "translation" and "context_translation" as output. If I provide "definitions", you should try to select the appropriate one for the given context, and return the id of selected definition as "id". If none are suitable, generate a new definition for me. If no context is provided, return the most common definition. If you do not know the appropriate definition, return an empty string for "definition" and "translation".
Expand Down
25 changes: 5 additions & 20 deletions enjoy/src/commands/punctuate.command.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { textCommand } from "./text.command";

export const punctuateCommand = async (
text: string,
Expand All @@ -10,29 +10,14 @@ export const punctuateCommand = async (
baseUrl?: string;
}
): Promise<string> => {
const { key, temperature = 0, baseUrl } = options;
let { modelName = "gpt-4-turbo" } = options;
if (!text) throw new Error("Text is required");

const chatModel = new ChatOpenAI({
openAIApiKey: key,
modelName,
temperature,
configuration: {
baseURL: baseUrl,
},
cache: false,
verbose: true,
maxRetries: 2,
});

const prompt = ChatPromptTemplate.fromMessages([
const prompt = await ChatPromptTemplate.fromMessages([
["system", SYSTEM_PROMPT],
["human", text],
]);

const response = await prompt.pipe(chatModel).invoke({});
]).format({});

return response.text;
return textCommand(prompt, options);
};

const SYSTEM_PROMPT = `Please add proper punctuation to the text I provide you. Return the corrected text only.`;
Loading
Loading