Skip to content

Commit

Permalink
📦 NEW: English (CEFR) level assessment bot (#4)
Browse files Browse the repository at this point in the history
* gitignore

* opening for cefr ai bot

* header for cefr ai bot

* nextjs chatui

* udpate readme for cefr level assessment bot

* update layout to include meta  for cefr level assessment bot

* spelling corrected

* udpate package name for cefr level assessment bot
  • Loading branch information
AIENGINE committed Jul 23, 2024
1 parent 49b2ae0 commit 1b9d723
Show file tree
Hide file tree
Showing 32 changed files with 1,829 additions and 0 deletions.
54 changes: 54 additions & 0 deletions examples/cefr-level-assessment-bot/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env
.env*.local
.copy.local.env
.copy.remote.env

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

# Supabase
seed.sql
xseed.sql
xxseed.sql
-seed.sql
/supabase/seed.sql
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

# No lock files.
package-lock.json
yarn.lock
dist
76 changes: 76 additions & 0 deletions examples/cefr-level-assessment-bot/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
![License: MIT][mit] [![Fork to ⌘ Langbase][fork]][pipe]

## Build English (CEFR) Level Assessment Bot with Pipes — ⌘ Langbase

This chatbot is built by using an AI Pipe on Langbase, it works with 30+ LLMs (OpenAI, Gemini, Mistral, Llama, Gemma, etc), any Data (10M+ context with Memory sets), and any Framework (standard web API you can use with any software).

Check out the live demo [here][demo].

## Features

- 💬 [CEFR Level Assessment Bot][demo] — Built with an [AI Pipe on ⌘ Langbase][pipe]
- ⚡️ Streaming — Real-time chat experience with streamed responses
- 🗣️ Q/A — Ask questions and get pre-defined answers with your preferred AI model and tone
- 🔋 Responsive and open source — Works on all devices and platforms

## Learn more

1. Check the [CEFR Level Assessment Bot on ⌘ Langbase][pipe]
2. Read the [source code on GitHub][gh] for this example
3. Go through Documentaion: [Pipe Quick Start][qs]
4. Learn more about [Pipes & Memory features on ⌘ Langbase][docs]

## Get started

Let's get started with the project:

To get started with Langbase, you'll need to [create a free personal account on Langbase.com][signup] and verify your email address. _Done? Cool, cool!_

1. Fork the [CEFR Level Assessment Bot][pipe] Pipe on ⌘ Langbase.
2. Go to the API tab to copy the Pipe's API key (to be used on server-side only).
3. Download the example project folder from [here][download] or clone the reppository.
4. `cd` into the project directory and open it in your code editor.
5. Duplicate the `.env.example` file in this project and rename it to `.env.local`.
6. Add the following environment variables (.env.local):
```
# Replace `PIPE_API_KEY` with the copied API key.
NEXT_LB_PIPE_API_KEY="PIPE_API_KEY"
```
7. In your CLI issue the following:
```sh
# Install the dependencies using the following command:
npm install

# Run the project using the following command:
npm run dev
```

8. Your app template should now be running on [localhost:3000][local].

> NOTE:
> This is a Next.js project, so you can build and deploy it to any platform of your choice, like Vercel, Netlify, Cloudflare, etc.
---

## Authors

This project is created by [Langbase][lb] team members, with contributions from:

- Muhammad-Ali Danish - Software Engineer, [Langbase][lb]

**_Built by ⌘ [Langbase.com][lb] — Ship hyper-personalized AI assistants with memory!_**


[demo]: https://cefr-level-assessment-bot.langbase.dev
[lb]: https://langbase.com
[pipe]: https://beta.langbase.com/examples/cefr-level-assessment-bot
[gh]: https://github.com/LangbaseInc/langbase-examples/tree/main/examples/cefr-level-assessment-bot
[download]:https://download-directory.github.io/?url=https://github.com/LangbaseInc/langbase-examples/tree/main/examples/cefr-level-assessment-bot
[signup]: https://langbase.fyi/io
[qs]:https://langbase.com/docs/pipe/quickstart
[docs]:https://langbase.com/docs
[xaa]:https://x.com/MrAhmadAwais
[xab]:https://x.com/AhmadBilalDev
[local]:http://localhost:3000
[mit]: https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge&color=%23000000
[fork]: https://img.shields.io/badge/FORK%20ON-%E2%8C%98%20Langbase-000000.svg?style=for-the-badge&logo=%E2%8C%98%20Langbase&logoColor=000000
57 changes: 57 additions & 0 deletions examples/cefr-level-assessment-bot/app/api/chat/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { OpenAIStream, StreamingTextResponse } from 'ai'

export const runtime = 'edge'

/**
* Stream AI Chat Messages from Langbase
*
* @param req
* @returns
*/
export async function POST(req: Request) {
try {
if (!process.env.NEXT_LB_PIPE_API_KEY) {
throw new Error(
'Please set NEXT_LB_PIPE_API_KEY in your environment variables.'
)
}

const endpointUrl = 'https://api.langbase.com/beta/chat'

const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.NEXT_LB_PIPE_API_KEY}`
}

// Get chat prompt messages and threadId from the client.
const body = await req.json()
const { messages, threadId } = body

const requestBody = {
messages,
...(threadId && { threadId }) // Only include threadId if it exists
}

// Send the request to Langbase API.
const response = await fetch(endpointUrl, {
method: 'POST',
headers,
body: JSON.stringify(requestBody)
})

if (!response.ok) {
const res = await response.json()
throw new Error(`Error ${res.error.status}: ${res.error.message}`)
}

// Handle Langbase response, which is a stream in OpenAI format.
const stream = OpenAIStream(response)
// Respond with a text stream.
return new StreamingTextResponse(stream, {
headers: response.headers
})
} catch (error: any) {
console.error('Uncaught API Error:', error)
return new Response(JSON.stringify(error), { status: 500 })
}
}
Binary file not shown.
99 changes: 99 additions & 0 deletions examples/cefr-level-assessment-bot/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

/* Zinc */
/* --background: 240 10% 3.9%; */
/* --muted: 240 3.7% 15.9%; */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--card: 0 0% 100%;
--card-foreground: 240 10% 3.9%;
--popover: 0 0% 100%;
--popover-foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
/* --destructive: 0 84.2% 60.2%; */
--destructive: 2.74 92.59% 62.94%;
--destructive-foreground: 0 0% 98%;
--warning: 46.38 70.61% 48.04%;
--warning-foreground: 120 12.5% 3.14%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 6px;
--danger: 2.74 92.59% 62.94%;
}

.dark {
/* --background: 120 12.5% 3.14%; */
--background: 240, 3%, 9%;
--foreground: 0 0% 98%;
--card: 240 10% 3.9%;
--card-foreground: 0 0% 98%;
--popover: 240 10% 3.9%;
--popover-foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 98%;
/* --muted: 165 10% 7.84%; */
--muted: 240 3.45% 11.37%;
--muted-foreground: 240 5% 64.9%;
--accent: 240 3.7% 15.9%;
--accent-foreground: 0 0% 98%;
/* --destructive: 0 62.8% 30.6%; */
--destructive: 356.18 70.61% 48.04%;
--destructive-foreground: 0 0% 98%;
--warning: 46.38 70.61% 48.04%;
--warning-foreground: 120 12.5% 3.14%;
/* --border: 240 3.7% 15.9%; */
--border: 240 2% 14%;
--border-muted: 240 2% 14%;
--input: 240 3.7% 15.9%;
--ring: 240 4.9% 83.9%;
--danger: 356.18 70.61% 48.04%;
}
}

@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}

::selection {
color: hsl(var(--background));
background: hsl(var(--foreground));
}

.google {
display: inline-block;
width: 20px;
height: 20px;
position: relative;
background-size: contain;
background-repeat: no-repeat;
background-position: 50%;
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 48 48'%3E%3Cdefs%3E%3Cpath id='a' d='M44.5 20H24v8.5h11.8C34.7 33.9 30.1 37 24 37c-7.2 0-13-5.8-13-13s5.8-13 13-13c3.1 0 5.9 1.1 8.1 2.9l6.4-6.4C34.6 4.1 29.6 2 24 2 11.8 2 2 11.8 2 24s9.8 22 22 22c11 0 21-8 21-22 0-1.3-.2-2.7-.5-4z'/%3E%3C/defs%3E%3CclipPath id='b'%3E%3Cuse xlink:href='%23a' overflow='visible'/%3E%3C/clipPath%3E%3Cpath clip-path='url(%23b)' fill='%23FBBC05' d='M0 37V11l17 13z'/%3E%3Cpath clip-path='url(%23b)' fill='%23EA4335' d='M0 11l17 13 7-6.1L48 14V0H0z'/%3E%3Cpath clip-path='url(%23b)' fill='%2334A853' d='M0 37l30-23 7.9 1L48 0v48H0z'/%3E%3Cpath clip-path='url(%23b)' fill='%234285F4' d='M48 48L17 24l-4-3 35-10z'/%3E%3C/svg%3E");
}

@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
36 changes: 36 additions & 0 deletions examples/cefr-level-assessment-bot/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { Header } from '@/components/header'
import cn from 'mxcn'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import { Toaster } from 'sonner'
import './globals.css'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
title: 'English (CEFR) Level Assessment Bot - Langbase',
description: 'Build an English (CEFR) Level Assessment Bot with ⌘ Langbase using any LLM model.',
keywords: ['English', 'CEFR Level Assessment Bot', 'Langbase']
}

export default function RootLayout({
children
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className={cn(inter.className, 'dark bg-background')}>
<div className="flex min-h-screen flex-col px-3 pr-0 pt-6">
<div className="rounded-l-[calc(var(--radius)+2px)] border border-r-0 pb-1 pl-1">
<Toaster />
<Header />
<main className="rounded-l-[calc(var(--radius)+2px)] bg-muted">
{children}
</main>
</div>
</div>
</body>
</html>
)
}
7 changes: 7 additions & 0 deletions examples/cefr-level-assessment-bot/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Chatbot } from '@/components/chatbot-page'

export const runtime = 'edge'

export default function ChatPage() {
return <Chatbot />
}
Loading

0 comments on commit 1b9d723

Please sign in to comment.