mirror of
https://github.com/Andriy-Kulak/ai-naval.git
synced 2024-11-25 16:08:31 +08:00
improved docs and code
This commit is contained in:
parent
fb4d2f0d9f
commit
c15b582e3a
41
README.md
41
README.md
@ -1,16 +1,36 @@
|
||||
## Tu Tutor
|
||||
## Research Project Creating AI Ravikant
|
||||
|
||||
Weekend project where I learned how to use open ai chatpot, eleven labs, prompt engineering to have an ai tutor to speak with and improve my spanish! I took some inspiration & code from Aleem's [Espanol Love Repo](https://github.com/aleemrehmtulla/espanol-love) :-)
|
||||
This is a weekend project where I learned how to use open ai chatbot, langchain-js, elevenlabs, prompt engineering & using extra information like books to improve the experience when talking to chatbot.
|
||||
|
||||
I used the book, "ALMANACK OF NAVAL RAVIKANT" to create a vector database and index the data.
|
||||
|
||||
**This project is not related to real Naval Ravikant and is a research project only**
|
||||
|
||||
The way this app works is when the user asks a question, we look through the vector database and provide 4 most relevant context snippets from the book that are each 2,000 characters long and send it to open ai as additional context so that it can provide a better response
|
||||
|
||||
For more content, you can follow me on twitter [here](https://twitter.com/emergingbits)
|
||||
|
||||
### Setup
|
||||
|
||||
1. Grab an openai api key from [here](https://beta.openai.com/) and add it to your .env file
|
||||
1. Grab an openai api key from [here](https://beta.openai.com/) and add it to your `.env` file that you will want to create in root folder
|
||||
2. Grab an ElevenLabs api key from [here](https://beta.elevenlabs.io/speech-synthesis) and add it to your .env file
|
||||
3. Clone a voice with ElevenLabs and add the model id to your .env file
|
||||
4. Hit `npm install` to grab the necessary packages
|
||||
5. Run `npm run dev` to start your server on `http://localhost:3000`
|
||||
5. Go to [pinecone](https://www.pinecone.io/) and create an index with these parameters:
|
||||
|
||||
- euclidian algo
|
||||
- 1536 dimensions
|
||||
|
||||
When you finish that, you need to add vars with those values `PINECONE_ENVIRONMENT=`, `PINECONE_API_KEY=`
|
||||
and `PINECONE_INDEX={name of index you created}`
|
||||
|
||||
6. If you don't have `ts-node` or `pdf-parse` installed, please install globally so you can run script to add indexing to pinecone
|
||||
|
||||
`npm install -g ts-node pdf-parse`
|
||||
|
||||
7. I ran the script to add indexing to pinecone `ts-node scripts/createIndex.ts`. Feel free to adjust it for your needs. You can use all kinds of file types including txt, pdf, etc.
|
||||
|
||||
8. Run `npm run dev` to start your server on `http://localhost:3000`
|
||||
|
||||
### Deploy to the world
|
||||
|
||||
@ -20,11 +40,15 @@ For more content, you can follow me on twitter [here](https://twitter.com/emergi
|
||||
|
||||
### Other Useful Notes
|
||||
|
||||
When setting up eleven labs, you need to configure voices to get the proper `ELEVENLABS_VOICE_ID`
|
||||
1. Langchain docs: https://js.langchain.com/docs/
|
||||
|
||||
- great documentation for interacting with pinecone
|
||||
|
||||
2. When setting up eleven labs, you need to configure voices to get the proper `ELEVENLABS_VOICE_ID`
|
||||
|
||||
- https://docs.elevenlabs.io/api-reference/voices
|
||||
|
||||
Open AI has rate limits. This repo is using open ai 3.5. if you have access to 4.0, you can switch the model!
|
||||
3. Open AI has rate limits. This repo is using open ai 3.5. if you have access to 4.0, you can switch the model!
|
||||
|
||||
- https://platform.openai.com/account/rate-limits
|
||||
|
||||
@ -32,7 +56,7 @@ To properly configure open ai for best experience, refer to deep learning course
|
||||
|
||||
- improve prompting with: https://learn.deeplearning.ai/chatgpt-prompt-eng/lesson/8/chatbot
|
||||
|
||||
Open AI does a fairly good job with translating but it's not perfect. Here is another provider for more precise translation:
|
||||
4. Open AI does a fairly good job with translating but it's not perfect. Here is another provider for more precise translation:
|
||||
|
||||
- https://www.deepl.com/translator
|
||||
|
||||
@ -42,8 +66,5 @@ Open AI does a fairly good job with translating but it's not perfect. Here is an
|
||||
|
||||
## To Do
|
||||
|
||||
- create a JS script for embedding vector dbs
|
||||
- update docs
|
||||
- update voice
|
||||
- rename api
|
||||
- had to install `npm install pdf-parse`
|
||||
|
@ -88,7 +88,11 @@ async function askOpenAI({
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: `Imagine you are Naval Ravikant and you want to give advice to the user you're interacting with that may ask you questions or advice. The user's name is ${userName}. I will provide you context snippets from "The Almanack of Naval Ravikant" from a vecor database to help you answer the user's questions. Introduce youself to ${userName}"`,
|
||||
content: `
|
||||
Imagine you are Naval Ravikant and you want to give advice to the user you're interacting with that may ask you questions or advice. The user's name is ${userName}.
|
||||
I will provide you context snippets from "The Almanack of Naval Ravikant" from a vecor database to help you answer the user's questions.
|
||||
Introduce youself to ${userName}. Don't mention context snippets when replying.
|
||||
`,
|
||||
},
|
||||
...(messages || [
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import Head from "next/head";
|
||||
import { FaMicrophone, FaTwitter } from "react-icons/fa";
|
||||
import { FaTwitter } from "react-icons/fa";
|
||||
import Beatloader from "react-spinners/BeatLoader";
|
||||
import base64ToBlob from "@/utils/basetoblob";
|
||||
import {
|
||||
@ -19,18 +19,8 @@ import {
|
||||
import { handleEnterKeyPress } from "@/utils";
|
||||
import NameInput from "@/components/NameInput";
|
||||
import { Message } from "@/types";
|
||||
import useIsChrome from "@/hooks/useIsChrome";
|
||||
|
||||
let SpeechRecognition: { new (): SpeechRecognition };
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
SpeechRecognition =
|
||||
window.SpeechRecognition || window.webkitSpeechRecognition;
|
||||
}
|
||||
|
||||
function Home() {
|
||||
const isChrome = useIsChrome();
|
||||
const micRef = useRef<SpeechRecognition>();
|
||||
const audioRef = useRef<HTMLAudioElement | null>(null);
|
||||
|
||||
const [messages, setMessages] = useState<Message[]>([]);
|
||||
@ -40,13 +30,8 @@ function Home() {
|
||||
};
|
||||
|
||||
const toast = useToast();
|
||||
|
||||
const [isListening, setIsListening] = useState(false);
|
||||
const [text, setText] = useState("");
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [isRecording, setIsRecording] = useState<boolean>(false);
|
||||
const [speechRecognition, setSpeechRecognition] =
|
||||
useState<SpeechRecognition | null>(null);
|
||||
|
||||
// on the first translate, we need to get the user's name
|
||||
// on subsequent translates, we can use the name from state
|
||||
@ -76,7 +61,7 @@ function Home() {
|
||||
setLoading(true);
|
||||
|
||||
// response for chat gpt
|
||||
const response = await fetch("/api/translate", {
|
||||
const response = await fetch("/api/chat", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@ -114,47 +99,11 @@ function Home() {
|
||||
await audioRef.current.play();
|
||||
};
|
||||
|
||||
// testing
|
||||
const handleListen = async (mic: any) => {
|
||||
if (!SpeechRecognition)
|
||||
return alert("Speech recognition is not available in your browser.");
|
||||
|
||||
mic.continuous = true;
|
||||
mic.interimResults = true;
|
||||
mic.lang = "es-ES";
|
||||
|
||||
if (isListening) mic.start();
|
||||
if (!isListening) mic.stop();
|
||||
|
||||
mic.onresult = (event: SpeechRecognitionEvent) => {
|
||||
const transcript = Array.from(event.results)
|
||||
.map((result) => result[0])
|
||||
.map((result) => result.transcript)
|
||||
.join("");
|
||||
setText(transcript);
|
||||
mic.onerror = (event: SpeechRecognitionErrorEvent) => {
|
||||
console.log(event.error);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const mic = new SpeechRecognition();
|
||||
|
||||
micRef.current = mic;
|
||||
|
||||
const audio = new Audio();
|
||||
audioRef.current = audio;
|
||||
|
||||
return () => {
|
||||
mic.stop();
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
handleListen(micRef.current);
|
||||
}, [isListening]);
|
||||
|
||||
const userBgColor = useColorModeValue("blue.500", "blue.300");
|
||||
const assistantBgColor = useColorModeValue("gray.100", "gray.700");
|
||||
const userColor = "white";
|
||||
@ -169,7 +118,7 @@ function Home() {
|
||||
<Head>
|
||||
<title>Naval AI Bot</title>
|
||||
</Head>
|
||||
<VStack pt={40} px={4} spacing={4} h="100vh" maxW="600px" mx="auto">
|
||||
<VStack pt={40} px={4} mb={100} spacing={4} maxW="600px" mx="auto">
|
||||
<Heading as="h1" color="black">
|
||||
AI Naval That Gives Advice
|
||||
</Heading>
|
||||
@ -185,9 +134,6 @@ function Home() {
|
||||
<Icon as={FaTwitter} fontSize="md" />
|
||||
</Link>
|
||||
</Text>
|
||||
<Text color="black" as="i">
|
||||
<b> Microphone works well in Google Chrome only (for now).</b>
|
||||
</Text>
|
||||
|
||||
{!userName ? (
|
||||
<NameInput
|
||||
@ -243,26 +189,22 @@ function Home() {
|
||||
variant="outline"
|
||||
onClick={() => {
|
||||
translate();
|
||||
|
||||
console.log(
|
||||
"document.body.scrollHeight",
|
||||
document.body.scrollHeight
|
||||
);
|
||||
window.scrollTo({
|
||||
left: 0,
|
||||
top: document.body.scrollHeight,
|
||||
behavior: "smooth",
|
||||
});
|
||||
}}
|
||||
isLoading={loading}
|
||||
spinner={<Beatloader size={8} />}
|
||||
>
|
||||
Send
|
||||
</Button>
|
||||
{isChrome && (
|
||||
<Icon
|
||||
as={FaMicrophone}
|
||||
cursor="pointer"
|
||||
color={isListening ? "red.500" : "gray.500"}
|
||||
onClick={() => {
|
||||
if (isListening === true) {
|
||||
translate();
|
||||
}
|
||||
setIsListening(!isListening);
|
||||
setText("");
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</HStack>
|
||||
</>
|
||||
)}
|
||||
|
Loading…
Reference in New Issue
Block a user