-
Notifications
You must be signed in to change notification settings - Fork 9
Memory Playground #96
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
ce3b97e
4561299
e3da521
1d4f628
62dd17b
600d614
9811b25
a76ae63
ec200b2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
3.12 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Memory Server | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't want to spend too much extra time on this tool, but it would be worth considering how we could combine the efforts in the sample and this. (i.e. the sample has a web component that is really simple to show a user's memories). Just a consideration, not actionable. |
||
FastAPI wrapper around the memory module. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the future, do we want to consider having the wrapper as separate package so people don't need to download the related dependencies if they want to? (Can file for discussion and close this comment if anyone agrees) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure what you mean since the wrapper is already a separate package. It's under There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. as in, if we were publishing it, don't publish it with the rest of the code (bloat). but I'm still unclear on the publishing bit haha. |
||
|
||
|
||
## Setup Instructions | ||
|
||
To set up and run the Memory Server, follow these steps: | ||
|
||
1. Set up the dependencies by doing `uv sync` in the root folder. | ||
1. Ensure the virtual environment activated in your terminal. See the root README.md file for details. | ||
1. Configure the memory module in the `memory_service.py` file. | ||
1. Navigate to this folder and run the following command: | ||
|
||
```sh | ||
uvicorn main:app | ||
``` | ||
|
||
This will start the FastAPI server on port 8000. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import routes | ||
from fastapi import FastAPI | ||
from fastapi.middleware.cors import CORSMiddleware | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmmmmm fastapi is a very old package and not maintained. We should find a better solution for v next |
||
|
||
app = FastAPI(title="Chat API") | ||
|
||
# CORS configuration | ||
app.add_middleware( | ||
CORSMiddleware, | ||
allow_origins=["http://localhost:5173"], # Frontend URL | ||
allow_credentials=True, | ||
allow_methods=["*"], | ||
allow_headers=["*"], | ||
) | ||
|
||
# Include routers | ||
app.include_router(routes.router, tags=["memory"]) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import os | ||
import sys | ||
import uuid | ||
from datetime import datetime | ||
from typing import Optional | ||
|
||
sys.path.append(os.path.join(os.path.dirname(__file__), "../")) | ||
|
||
from memory_module import LLMConfig, MemoryModule, MemoryModuleConfig | ||
from memory_module.interfaces.types import AssistantMessageInput, MessageInput, UserMessageInput | ||
|
||
|
||
class MemoryService: | ||
def __init__(self, openai_api_key: str): | ||
# Initialize memory module | ||
config = MemoryModuleConfig( | ||
db_path=os.path.join(os.path.dirname(__file__), "../memory_module/data/memory.db"), | ||
llm=LLMConfig(model="gpt-4o", embedding_model="text-embedding-3-small", api_key=openai_api_key), | ||
) | ||
self._memory = MemoryModule(config) | ||
|
||
async def add_message(self, type: str, content: str): | ||
message: MessageInput | ||
if type == "assistant": | ||
message = AssistantMessageInput(id=str(uuid.uuid4()), content=content, author_id="1", conversation_ref="1") | ||
elif type == "user": | ||
message = UserMessageInput( | ||
id=str(uuid.uuid4()), content=content, author_id="1", conversation_ref="1", created_at=datetime.now() | ||
) | ||
else: | ||
raise ValueError("Invalid message type") | ||
|
||
await self._memory.add_message(message) | ||
|
||
async def retrieve_memories(self, query: str, user_id: str, limit: Optional[int] = None): | ||
return await self._memory.retrieve_memories(query, user_id=user_id, limit=limit) | ||
|
||
async def get_all_memories(self, user_id: str): | ||
return await self._memory.get_user_memories(user_id=user_id) |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,19 @@ | ||||||
[project] | ||||||
name = "memory-server" | ||||||
version = "0.1.0" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. version must be directly below [project]. Just did a PR that fixed this elsewhere :D |
||||||
description = "Add your description here" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. description |
||||||
readme = "README.md" | ||||||
requires-python = ">=3.12" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you change to
Suggested change
|
||||||
dependencies = [ | ||||||
"memory-module", | ||||||
"fastapi==0.115.6", | ||||||
"pydantic", | ||||||
"python-dotenv", | ||||||
"uvicorn" | ||||||
] | ||||||
|
||||||
[tool.uv] | ||||||
package = false | ||||||
|
||||||
[tool.uv.sources] | ||||||
memory-module = { workspace = true } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import os | ||
import sys | ||
|
||
from dotenv import load_dotenv | ||
from fastapi import APIRouter | ||
from memory_service import MemoryService | ||
from pydantic import BaseModel | ||
|
||
sys.path.append(os.path.join(os.path.dirname(__file__), "..")) | ||
|
||
from memory_module.interfaces.types import Memory | ||
|
||
load_dotenv() | ||
|
||
router = APIRouter() | ||
openai_api_key = os.environ.get("OPENAI_API_KEY") | ||
memory_service = MemoryService(openai_api_key=openai_api_key) | ||
|
||
|
||
@router.get("/memories", response_model=list[Memory]) | ||
corinagum marked this conversation as resolved.
Show resolved
Hide resolved
|
||
async def get_memories(user_id: str): | ||
return await memory_service.get_all_memories(user_id=user_id) | ||
|
||
|
||
class SearchQueryRequest(BaseModel): | ||
query: str | ||
user_id: str | ||
limit: int | ||
|
||
|
||
@router.post("/search") | ||
async def search_memories(request: SearchQueryRequest): | ||
if not request.user_id: | ||
raise ValueError("User ID is required to search memories") | ||
|
||
print(request) | ||
if len(request.query) > 0: | ||
return await memory_service.retrieve_memories(request.query, request.user_id, request.limit) | ||
else: | ||
# Return all memories if no query is provided | ||
return await memory_service.get_all_memories(user_id=request.user_id) | ||
|
||
|
||
class AddMessageRequest(BaseModel): | ||
type: str | ||
content: str | ||
|
||
|
||
@router.post("/message") | ||
async def add_message(request: AddMessageRequest): | ||
await memory_service.add_message(request.type, request.content) | ||
return {"message": "Message added successfully"} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
OPENAI_API_KEY= |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Memory Playground UI | ||
|
||
A simple web application to easily view and interact with the memory module. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Worth adding that this isn't meant for production |
||
|
||
## Setup Instructions | ||
|
||
To set up and run the playground, follow these steps: | ||
|
||
1. Navigate to this folder in the termainl. | ||
1. Set up the dependencies by doing `pnpm install` in the root folder. | ||
1. Run `pnpm run dev` to start the application on port 5173. | ||
1. Ensure that the memory server is configured and running locally. See `packages/memory-server`. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Link to memory server readme? |
||
|
||
## Notes | ||
The memory server base url is defined in the `api/memoryServer.ts` file. By default it points to http://127.0.0.1:8000, i.e localhost:8000 | ||
|
||
# Disclaimer | ||
|
||
Some components were taken from [TailAdmin](https://tailadmin.com/)'s free to use component package, which is under the MIT License. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you haven't already, this disclaimer should be where that code is |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import js from '@eslint/js'; | ||
import globals from 'globals'; | ||
import reactHooks from 'eslint-plugin-react-hooks'; | ||
import reactRefresh from 'eslint-plugin-react-refresh'; | ||
import tseslint from 'typescript-eslint'; | ||
|
||
export default tseslint.config( | ||
{ ignores: ['dist'] }, | ||
{ | ||
extends: [js.configs.recommended, ...tseslint.configs.recommended], | ||
files: ['**/*.{ts,tsx}'], | ||
languageOptions: { | ||
ecmaVersion: 2020, | ||
globals: globals.browser, | ||
}, | ||
plugins: { | ||
'react-hooks': reactHooks, | ||
'react-refresh': reactRefresh, | ||
}, | ||
rules: { | ||
...reactHooks.configs.recommended.rules, | ||
'react-refresh/only-export-components': [ | ||
'warn', | ||
{ allowConstantExport: true }, | ||
], | ||
'@typescript-eslint/no-explicit-any': 'warn', | ||
}, | ||
} | ||
); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!doctype html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Memory Playground</title> | ||
</head> | ||
<body> | ||
<div id="root"></div> | ||
<script type="module" src="/src/main.tsx"></script> | ||
</body> | ||
</html> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO for later: unit tests. Same for the playground.