Skip to content

ajkendal/scrimba-bot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

7 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿค– Scrimb Bot

Scrimb Bot is the hands-on project youโ€™ll build throughout the Build AI Apps with LangChain.js course.
It showcases how to use LangChain.js to create a working AI chatbot from scratch, with prompts, chains, and memory.


๐ŸŽฏ About the Course

This project is developed as part of the Scrimba course Build AI Apps with LangChain.js.
The course guides you step by step through:

  • Setting up LangChain.js in a Node.js environment
  • Designing prompts and building chains
  • Adding memory to conversations
  • Extending bots with tools and external data sources
  • Deploying and experimenting with AI apps

By the end of the course, youโ€™ll have your own chatbot (Scrimb Bot) and the skills to extend it further.


๐Ÿš€ Features

  • Console-based chatbot powered by LangChain.js
  • Structured prompts with role separation
  • Conversation memory for context-aware replies
  • Supabase integration for storing and retrieving data
  • OpenAI API for intelligent responses
  • Modular design for extending with new chains/tools
  • Built with modern JavaScript practices

๐Ÿ“ฆ Tech Stack

  • LangChain.js โ€“ framework for AI applications
  • OpenAI โ€“ language model API
  • Supabase โ€“ database and vector store
  • Node.js โ€“ runtime
  • npm โ€“ dependency management
  • dotenv โ€“ environment variables

Workflow

Workflow Diagram


๐Ÿ—„๏ธ Setting Up the Database with Supabase

import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import { createClient } from '@supabase/supabase-js';
import { SupabaseVectorStore } from 'langchain/vectorstores/supabase';
import { OpenAIEmbeddings } from 'langchain/embeddings/openai';

// @supabase/supabase-js
try {
  const result = await fetch('scrimba-info.txt');
  const text = await result.text();
  const splitter = new RecursiveCharacterTextSplitter({
    chunkSize: 500,
    chunkOverlap: 50,
    separators: ['\n\n', '\n', ' ', ''], // default setting
  });

  const output = await splitter.createDocuments([text]);

  const sbApiKey = process.env.SUPABASE_API_KEY;
  const sbUrl = process.env.SUPABASE_URL_LC_CHATBOT;
  const openAIApiKey = process.env.OPENAI_API_KEY;

  const client = createClient(sbUrl, sbApiKey);

  await SupabaseVectorStore.fromDocuments(
    output,
    new OpenAIEmbeddings({ openAIApiKey }),
    {
      client,
      tableName: 'documents',
    }
  );
  console.log('success');
} catch (err) {
  console.log(err);
}

๐Ÿ“ Starter Code

When you first begin the course, your entry file (index.js, index.html, index.css) may look something like this:

document.addEventListener('submit', (e) => {
  e.preventDefault();
  progressConversation();
});

const openAIApiKey = process.env.OPENAI_API_KEY;

async function progressConversation() {
  const userInput = document.getElementById('user-input');
  const chatbotConversation = document.getElementById(
    'chatbot-conversation-container'
  );
  const question = userInput.value;
  userInput.value = '';

  // add human message
  const newHumanSpeechBubble = document.createElement('div');
  newHumanSpeechBubble.classList.add('speech', 'speech-human');
  chatbotConversation.appendChild(newHumanSpeechBubble);
  newHumanSpeechBubble.textContent = question;
  chatbotConversation.scrollTop = chatbotConversation.scrollHeight;

  // add AI message
  const newAiSpeechBubble = document.createElement('div');
  newAiSpeechBubble.classList.add('speech', 'speech-ai');
  chatbotConversation.appendChild(newAiSpeechBubble);
  newAiSpeechBubble.textContent = result;
  chatbotConversation.scrollTop = chatbotConversation.scrollHeight;
}
<!DOCTYPE html>
<html>
  <head>
    <title>Scrimba Chatbot</title>
    <link rel="stylesheet" href="index.css" />
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins&family=Roboto&display=swap"
      rel="stylesheet"
    />
  </head>

  <body>
    <main>
      <section class="chatbot-container">
        <div class="chatbot-header">
          <img src="images/logo-scrimba.svg" class="logo" />
          <p class="sub-heading">Knowledge Bank</p>
        </div>
        <div
          class="chatbot-conversation-container"
          id="chatbot-conversation-container"
        ></div>
        <form id="form" class="chatbot-input-container">
          <input name="user-input" type="text" id="user-input" required />
          <button id="submit-btn" class="submit-btn">
            <img src="images/send.svg" class="send-btn-icon" />
          </button>
        </form>
      </section>
    </main>
    <script src="index.js" type="module"></script>
  </body>
</html>
:root {
  --border-rad-lg: 15px;
  --light-text: #fefefe;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  padding: 0;
  font-family: 'Poppins';
}

main {
  background-color: slategrey;
  background-image: url('images/scrimba-bg.jpeg');
  background-size: cover;
  background-repeat: no-repeat;
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* chatbot elements */

.chatbot-container {
  background-color: #171f26;
  width: 360px;
  min-height: 380px;
  border-radius: var(--border-rad-lg);
  padding: 1em;
}

.chatbot-container > * {
  padding: 0.5em;
}

.chatbot-header {
  display: flex;
  flex-direction: column;
  gap: 0.6em;
}

.logo {
  width: 160px;
}

.chatbot-conversation-container {
  height: 250px;
  overflow-y: scroll;
  margin: 1em 0;
}

/* stop ugly scroll bar on some browsers */
.chatbot-conversation-container::-webkit-scrollbar {
  display: none;
}

.chatbot-conversation-container::-moz-scrollbar {
  display: none;
}

.speech {
  padding: 1em;
  max-width: 240px;
  color: var(--light-text);
  min-width: 90%;
  border-radius: var(--border-rad-lg);
  font-size: 1.07em;
}

.speech:first-child {
  margin-top: 0;
}

.speech-ai {
  background: #334959;
  border-top-left-radius: 0;
  margin: 1.2em 1em 0 0;
}

.speech-human {
  margin: 1.2em 0 0 1em;
  background: #2f4f4f;
  border-top-right-radius: 0;
}

.chatbot-input-container {
  display: flex;
}

input[type='text'],
button {
  background-color: transparent;
  border: 1px solid #586e88;
  border-radius: var(--border-rad-lg);
  padding: 1em;
}

input[type='text'] {
  color: var(--light-text);
  width: 100%;
  border-right: 0;
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

button {
  border-left: 0;
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

.send-btn-icon {
  width: 20px;
  display: block;
}

/* text */
.sub-heading {
  color: #999999;
  font-family: 'Roboto', sans-serif;
  font-size: 12px;
  text-transform: uppercase;
  margin: 0;
}

This simple starting point helps you verify your setup and gives you a base to build on. As you progress through the course, youโ€™ll:

  • Import and configure LangChain.js
  • Add chains and prompt templates
  • Connect memory and Supabase
  • Integrate the OpenAI API

๐Ÿ“š Learning Outcomes

By completing this project, youโ€™ll learn how to:

  • Build AI apps with LangChain.js
  • Structure prompts and conversations
  • Add memory for contextual chatbots
  • Store and retrieve data with Supabase
  • Connect to the OpenAI API for responses
  • Deploy and iterate on AI applications

About

Scrimb Bot is a chatbot built in the Build AI Apps with LangChain.js course on Scrimba. It combines LangChain.js, OpenAI, and Supabase to demonstrate how to create AI-powered apps with memory, data storage, and intelligent responses.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors