询问导师¶
此示例演示了如何创建一组可以与之对话的“导师”。导师是使用 character-generator.ts
文件生成的。这将使用 Stable Beluga 70b 来创建每个人的简历以及他们常用的口头禅和常见短语列表。然后,mentors.ts
将接受一个问题,并选择三个“导师”开始与他们对话。有时他们会相互交谈,其他时候他们只是发表一系列独白。看他们做什么和说什么很有趣。
使用方法¶
1. 添加llama2,让导师回答您的问题:
2. 安装先决条件:
3. 提出问题:
您还可以添加您自己的角色,当您提问时随机选择。
1. 确保您已安装正确的模型:
2. 创建一个新角色:
您可以选择任何您喜欢的知名人物。此示例将创建 lornegreene/Modelfile
。
3. 现在您可以使用此命令创建一个模型:
username
是您在 https://ollama.com/signup 注册时设置的用户名。
4. 要将其添加到您的导师中,您需要按如下方式更新代码。在 mentors.ts
的第8行,添加一个对象到数组中,将 <username>
替换为您上面使用的用户名。
代码审查¶
在此示例中,您可以运行两个脚本。第一个是主脚本,用于询问导师问题。另一个让你生成一个角色以添加到导师中。这两个脚本主要是在每个推理阶段调整提示。
mentors.ts¶
在 main 函数中,它首先生成一组导师名单。这会从一系列有趣的角色中选择3个。然后我们请求一个问题,然后事情变得有趣。我们为三个导师设置了略有不同的提示。第二和第三个导师会看到前面的人说了什么。mentors
中的其他函数设置了每个导师的提示。
character-generator.ts¶
Character Generator 简单地自定义提示,为任何著名人物构建角色档案。大部分脚本只是在调整提示。这使用了 Stable Beluga 2 的 70b 参数。70b 模型在编写角色简介方面比小型模型表现得更好,而 Stable Beluga 似乎比 Llama 2 表现得更好。由于这在为角色开发时使用,它不影响询问导师输入的运行时。
源码¶
mentors.ts¶
import { Ollama } from 'ollama-node';
const mentorCount = 3;
const ollama = new Ollama();
type Mentor = { ns: string, char: string };
function getMentors(): Mentor[] {
const mentors = [{ ns: 'mattw', char: 'Gary Vaynerchuk' }, { ns: 'mattw', char: 'Kanye West'}, {ns: 'mattw', char: 'Martha Stewart'}, {ns: 'mattw', char: 'Neil deGrasse Tyson'}, {ns: 'mattw', char: 'Owen Wilson'}, {ns: 'mattw', char: 'Ronald Reagan'}, {ns: 'mattw', char: 'Donald Trump'}, {ns: 'mattw', char: 'Barack Obama'}, {ns: 'mattw', char: 'Jeff Bezos'}];
const chosenMentors: Mentor[] = [];
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: Mentor): string {
const model = mentor.char.toLowerCase().replace(/\s/g, '');
return `${mentor.ns}/${model}`;
}
async function getSystemPrompt(mentor: Mentor, isLast: boolean, question: string): Promise<string> {
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.char}: `);
for await (const chunk of ollama.streamingGenerate(theConversation + `Continue the conversation as if you were ${mentor.char} on the question "${question}".`)) {
if (chunk.response) {
output += chunk.response;
process.stdout.write(chunk.response);
} else {
process.stdout.write('\n');
}
}
theConversation += `${mentor.char}: ${output}\n\n`
}
}
main();
character-generator.ts¶
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();