Skip to content

Commit

Permalink
feature: add serverside function for app
Browse files Browse the repository at this point in the history
  • Loading branch information
AureliusIvan committed Jul 25, 2024
1 parent 8705f0e commit 2e95db5
Show file tree
Hide file tree
Showing 30 changed files with 871 additions and 114 deletions.
12 changes: 12 additions & 0 deletions docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
services:
qdrant:
image: qdrant/qdrant:v1.2.0
ports:
- "6333:6333"
volumes:
- qdrant_storage:/qdrant/storage
environment:
QDRANT__LOG_LEVEL: "INFO"

volumes:
qdrant_storage:
98 changes: 98 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
annotated-types==0.7.0
anyio==4.4.0
asttokens==2.4.1
attrs==23.2.0
backcall==0.2.0
backoff==2.2.1
beautifulsoup4==4.12.3
bleach==6.1.0
certifi==2024.7.4
charset-normalizer==3.3.2
click==8.1.7
decorator==5.1.1
defusedxml==0.7.1
distro==1.9.0
dnspython==2.6.1
docopt==0.6.2
email_validator==2.2.0
executing==2.0.1
fastapi==0.111.1
fastapi-cli==0.0.4
fastjsonschema==2.20.0
grpcio==1.65.1
grpcio-tools==1.65.1
h11==0.14.0
h2==4.1.0
hpack==4.0.0
httpcore==1.0.5
httptools==0.6.1
httpx==0.27.0
hyperframe==6.0.1
idna==3.7
ipython==8.12.3
jedi==0.19.1
Jinja2==3.1.4
jsonschema==4.23.0
jsonschema-specifications==2023.12.1
jupyter_client==8.6.2
jupyter_core==5.7.2
jupyterlab_pygments==0.3.0
markdown-it-py==3.0.0
MarkupSafe==2.1.5
matplotlib-inline==0.1.7
mdurl==0.1.2
mem0ai==0.0.9
mistune==3.0.2
monotonic==1.6
nbclient==0.10.0
nbconvert==7.16.4
nbformat==5.10.4
numpy==2.0.1
openai==1.37.0
packaging==24.1
pandocfilters==1.5.1
parso==0.8.4
pexpect==4.9.0
pickleshare==0.7.5
pipreqs==0.5.0
platformdirs==4.2.2
portalocker==2.10.1
posthog==3.5.0
prompt_toolkit==3.0.47
protobuf==5.27.2
ptyprocess==0.7.0
pure_eval==0.2.3
pydantic==2.8.2
pydantic_core==2.20.1
Pygments==2.18.0
python-dateutil==2.9.0.post0
python-dotenv==1.0.1
python-multipart==0.0.9
PyYAML==6.0.1
pyzmq==26.0.3
qdrant-client==1.10.1
referencing==0.35.1
requests==2.32.3
rich==13.7.1
rpds-py==0.19.1
setuptools==71.1.0
shellingham==1.5.4
six==1.16.0
sniffio==1.3.1
soupsieve==2.5
stack-data==0.6.3
starlette==0.37.2
tinycss2==1.3.0
tornado==6.4.1
tqdm==4.66.4
traitlets==5.14.3
typer==0.12.3
typing_extensions==4.12.2
urllib3==2.2.2
uvicorn==0.30.3
uvloop==0.19.0
watchfiles==0.22.0
wcwidth==0.2.13
webencodings==0.5.1
websockets==12.0
yarg==0.1.9
10 changes: 10 additions & 0 deletions script/export_env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash

# Check if .env file exists in the parent directory
if [ ! -f ../.env ]; then
echo "../.env file not found!"
exit 1
fi

# Export each variable from ../.env file
export $(grep -v '^#' ../.env | xargs)
Empty file added server/__init__.py
Empty file.
2 changes: 2 additions & 0 deletions server/api_test/test_main.http
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ GET http://127.0.0.1:8000/hello/User
Accept: application/json

###
GET http://127.0.0.1:8000/ask/hello
Accept: application/json
Empty file added server/domain/__init__.py
Empty file.
Empty file added server/domain/model/__init__.py
Empty file.
Empty file.
68 changes: 68 additions & 0 deletions server/domain/service/RememberService.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import os
from openai import OpenAI
from mem0 import Memory
from dotenv import load_dotenv

# dotenv_path = os.path.join(os.path.dirname(__file__), '../.env')
load_dotenv()

os.environ['OPENAI_API_KEY'] = os.getenv('OPENAI_API_KEY')

# Initialize the OpenAI client
client = OpenAI()


class RememberService:
def __init__(self):
"""
Initialize the PersonalAITutor with memory configuration and OpenAI client.
"""
# in case we want to change to qdrant
config = {
"vector_store": {
"provider": "qdrant",
"config": {
"host": os.getenv('QDRANT_HOST'),
"port": os.getenv('QDRANT_PORT'),
"api_key": os.getenv('QDRANT_API_KEY')
}
},
}
self.memory = Memory.from_config(config)
self.client = client
self.app_id = "app-1"
self.messages = [{"role": "system",
"content": """
Kamu adalah asisten personal bernama bear.
kamu akan membantu user meningat setiap peristiwa dan hal-hal yang diceritakan
"""}]

async def ask(self, question, user_id=1):
# Fetch previous related memories
previous_memories = self.get_memories(user_id=user_id)
prompt = question
if previous_memories:
prompt = f"User input: {question}\n Previous memories: {previous_memories}"
self.messages.append({"role": "user", "content": prompt})

# Generate response using GPT-4o
response = self.client.chat.completions.create(
model="gpt-3.5-turbo",
messages=self.messages
)
answer = response.choices[0].message.content
self.messages.append({"role": "assistant", "content": answer})

# Store the question in memory
self.memory.add(question, user_id=user_id)
return dict({
"message": answer
})

def get_memories(self, user_id):
memories = self.memory.get_all(user_id=user_id)
return [m['text'] for m in memories]

def search_memories(self, query, user_id):
memories = self.memory.search(query, user_id=user_id)
return [m['text'] for m in memories]
2 changes: 2 additions & 0 deletions server/domain/service/TriggerService.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class TriggerService:
pass
Empty file.
25 changes: 25 additions & 0 deletions server/main.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from server.domain.service.RememberService import RememberService
import backoff
import httpx

app = FastAPI()

origins = [
"http://localhost",
"http://localhost:3000", # Adjust based on your frontend's URL and port
"http://127.0.0.1:3000",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)


@app.get("/")
async def root():
Expand All @@ -11,3 +28,11 @@ async def root():
@app.get("/hello/{name}")
async def say_hello(name: str):
return {"message": f"Hello {name}"}


@backoff.on_exception(backoff.expo, httpx.RequestError, max_time=60)
@app.get("/ask/{prompt}")
async def ask(prompt: str):
ai = RememberService()
response = await ai.ask(prompt)
return response
15 changes: 15 additions & 0 deletions vercel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"version": 2,
"builds": [
{
"src": "./server/main.py",
"use": "@vercel/python"
}
],
"routes": [
{
"src": "/(.*)",
"dest": "/server/main.py"
}
]
}
3 changes: 2 additions & 1 deletion web/.env.example
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
CAPACITOR_ANDROID_STUDIO_PATH=
CAPACITOR_ANDROID_STUDIO_PATH=
NEXT_PUBLIC_SERVER_URL=
17 changes: 16 additions & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,32 @@
},
"dependencies": {
"@capacitor/android": "^6.1.1",
"@capacitor/camera": "^6.0.1",
"@capacitor/core": "^6.1.1",
"@capacitor/keyboard": "^6.0.1",
"@capacitor/local-notifications": "^6.0.0",
"@capacitor/network": "^6.0.1",
"@capacitor/push-notifications": "^6.0.1",
"@hookform/resolvers": "^3.9.0",
"@next-auth/firebase-adapter": "0.0.2-canary.207",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@vercel/analytics": "^1.3.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"firebase": "^10.12.4",
"lucide-react": "^0.414.0",
"next": "14.2.5",
"next-auth": "^4.24.7",
"react": "^18",
"react-dom": "^18",
"react-hook-form": "^7.52.1",
"react-icons": "^5.2.1",
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7"
"tailwindcss-animate": "^1.0.7",
"vaul": "^0.9.1",
"zod": "^3.23.8"
},
"devDependencies": {
"@capacitor/cli": "^6.1.1",
Expand Down
15 changes: 11 additions & 4 deletions web/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import type {Metadata} from "next";
import {Inter} from "next/font/google";
import "./globals.css";
import {Analytics} from "@vercel/analytics/react"
import React, {StrictMode} from "react";
import {Navbar} from "@/components/navbar";

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

Expand All @@ -17,10 +19,15 @@ export default function RootLayout({
}>) {
return (
<>
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
<Analytics/>
<StrictMode>
<html lang="en">
<body className={inter.className}>
<Navbar/>
{children}
</body>
</html>
<Analytics/>
</StrictMode>
</>
);
}
28 changes: 28 additions & 0 deletions web/src/app/login/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import type {Metadata} from "next";
import {Inter} from "next/font/google";
import {Analytics} from "@vercel/analytics/react"
import React from "react";

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

export const metadata: Metadata = {
title: "Remembear",
description: "An app for short term memory",
};

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<>
<html lang="en">
<body className={inter.className}>
{children}
</body>
</html>
<Analytics/>
</>
);
}
21 changes: 21 additions & 0 deletions web/src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Image from "next/image";
import Link from "next/link";
import {Button, buttonVariants} from "@/components/ui/button";
import {Textarea} from "@/components/ui/textarea";

export default function Login() {
return (
<form>
<main className="flex min-h-screen flex-col items-center p-2">
<h1>
Login
</h1>
<Link
href={"/"}
className={buttonVariants({variant: "default"})}>
Login with google
</Link>
</main>
</form>
);
}
Loading

0 comments on commit 2e95db5

Please sign in to comment.