diff --git a/examples/ask-the-mentors/.gitignore b/examples/ask-the-mentors/.gitignore new file mode 100644 index 00000000..d5f19d89 --- /dev/null +++ b/examples/ask-the-mentors/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json diff --git a/examples/ask-the-mentors/README.md b/examples/ask-the-mentors/README.md new file mode 100644 index 00000000..5b8349e8 --- /dev/null +++ b/examples/ask-the-mentors/README.md @@ -0,0 +1,21 @@ +# Ask the Mentors + +This example demonstrates how one would create a set of 'mentors' you can have a conversation with. The mentors are generated using the `character-generator.ts` file. This will use **Stable Beluga 70b** to create a bio and list of verbal ticks and common phrases used by each person. Then `mentors.ts` will take a question, and choose three of the 'mentors' and start a conversation with them. Occasionally, they will talk to each other, and other times they will just deliver a set of monologues. It's fun to see what they do and say. + +## Usage + +```bash +ts-node ./character-generator.ts "Lorne Greene" +``` + +This will create `lornegreene/Modelfile`. Now you can create a model with this command: + +```bash +ollama create lornegreene -f lornegreene/Modelfile +``` + +If you want to add your own mentors, you will have to update the code to look at your namespace instead of **mattw**. Also set the list of mentors to include yours. + +```bash +ts-node ./mentors.ts "What is a Jackalope?" +``` diff --git a/examples/ask-the-mentors/character-generator.ts b/examples/ask-the-mentors/character-generator.ts new file mode 100644 index 00000000..886eec67 --- /dev/null +++ b/examples/ask-the-mentors/character-generator.ts @@ -0,0 +1,26 @@ +import { Ollama } from 'ollama-node' +import fs from 'fs'; +import path from 'path'; + +async function characterGenerator() { + const character = process.argv[2]; + console.log(`You are creating a character for ${character}.`); + const foldername = character.replace(/\s/g, '').toLowerCase(); + const directory = path.join(__dirname, foldername); + if (!fs.existsSync(directory)) { + fs.mkdirSync(directory, { recursive: true }); + } + + const ollama = new Ollama(); + ollama.setModel("stablebeluga2:70b-q4_K_M"); + const bio = await ollama.generate(`create a bio of ${character} in a single long paragraph. Instead of saying '${character} is...' or '${character} was...' use language like 'You are...' or 'You were...'. Then create a paragraph describing the speaking mannerisms and style of ${character}. Don't include anything about how ${character} looked or what they sounded like, just focus on the words they said. Instead of saying '${character} would say...' use language like 'You should say...'. If you use quotes, always use single quotes instead of double quotes. If there are any specific words or phrases you used a lot, show how you used them. `); + + const thecontents = `FROM llama2\nSYSTEM """\n${bio.response.replace(/(\r\n|\n|\r)/gm, " ").replace('would', 'should')} All answers to questions should be related back to what you are most known for.\n"""`; + + fs.writeFile(path.join(directory, 'Modelfile'), thecontents, (err: any) => { + if (err) throw err; + console.log('The file has been saved!'); + }); +} + +characterGenerator(); \ No newline at end of file diff --git a/examples/ask-the-mentors/mentors.ts b/examples/ask-the-mentors/mentors.ts new file mode 100644 index 00000000..3c05b846 --- /dev/null +++ b/examples/ask-the-mentors/mentors.ts @@ -0,0 +1,59 @@ +import { Ollama } from 'ollama-node'; + +const mentorCount = 3; +const ollama = new Ollama(); + +function getMentors(): string[] { + const mentors = ['Gary Vaynerchuk', 'Kanye West', 'Martha Stewart', 'Neil deGrasse Tyson', 'Owen Wilson', 'Ronald Reagan', 'Donald Trump', 'Barack Obama', 'Jeff Bezos']; + const chosenMentors: string[] = []; + for (let i = 0; i < mentorCount; i++) { + const mentor = mentors[Math.floor(Math.random() * mentors.length)]; + chosenMentors.push(mentor); + mentors.splice(mentors.indexOf(mentor), 1); + } + return chosenMentors; +} + +function getMentorFileName(mentor: string): string { + const model = mentor.toLowerCase().replace(/\s/g, ''); + return `mattw/${model}`; +} + +async function getSystemPrompt(mentor: string, isLast: boolean, question: string): Promise { + ollama.setModel(getMentorFileName(mentor)); + const info = await ollama.showModelInfo() + let SystemPrompt = info.system || ''; + SystemPrompt += ` You should continue the conversation as if you were ${mentor} and acknowledge the people before you in the conversation. You should adopt their mannerisms and tone, but also not use language they wouldn't use. If they are not known to know about the concept in the question, don't offer an answer. Your answer should be no longer than 1 paragraph. And definitely try not to sound like anyone else. Don't repeat any slang or phrases already used. And if it is a question the original ${mentor} wouldn't have know the answer to, just say that you don't know, in the style of ${mentor}. And think about the time the person lived. Don't use terminology that they wouldn't have used.` + + if (isLast) { + SystemPrompt += ` End your answer with something like I hope our answers help you out`; + } else { + SystemPrompt += ` Remember, this is a conversation, so you don't need a conclusion, but end your answer with a question related to the first question: "${question}".`; + } + return SystemPrompt; +} + +async function main() { + const mentors = getMentors(); + const question = process.argv[2]; + let theConversation = `Here is the conversation so far.\nYou: ${question}\n` + + for await (const mentor of mentors) { + const SystemPrompt = await getSystemPrompt(mentor, mentor === mentors[mentorCount - 1], question); + ollama.setModel(getMentorFileName(mentor)); + ollama.setSystemPrompt(SystemPrompt); + let output = ''; + process.stdout.write(`\n${mentor}: `); + for await (const chunk of ollama.streamingGenerate(theConversation + `Continue the conversation as if you were ${mentor} on the question "${question}".`)) { + if (chunk.response) { + output += chunk.response; + process.stdout.write(chunk.response); + } else { + process.stdout.write('\n'); + } + } + theConversation += `${mentor}: ${output}\n\n` + } +} + +main(); \ No newline at end of file diff --git a/examples/ask-the-mentors/package.json b/examples/ask-the-mentors/package.json new file mode 100644 index 00000000..d4e37562 --- /dev/null +++ b/examples/ask-the-mentors/package.json @@ -0,0 +1,7 @@ +{ + "dependencies": { + "fs": "^0.0.1-security", + "ollama-node": "^0.0.3", + "path": "^0.12.7" + } +}