├── src ├── __init__.py ├── models │ ├── __init__.py │ ├── system.py │ ├── project.py │ ├── pagination.py │ ├── user.py │ ├── document.py │ └── retreival.py ├── endpoints │ ├── __init__.py │ ├── system.py │ └── retreival.py ├── constant.py ├── server.py ├── depedency.py ├── worker.py ├── worker_runner.py ├── lp_client.py ├── database.py ├── configuration.py ├── auth.py ├── pgai_client.py └── utils.py ├── tests ├── __init__.py └── test_sample.py ├── .python-version ├── frontend ├── .env.copy ├── public │ ├── interface.png │ ├── llama-logo.svg │ ├── vite.svg │ └── OFL.txt ├── .dockerignore ├── src │ ├── types │ │ ├── message.types.ts │ │ ├── theme.types.ts │ │ ├── search.types.ts │ │ ├── user.types.ts │ │ ├── api.types.ts │ │ ├── org.types.ts │ │ ├── dashboard.types.ts │ │ ├── project.types.ts │ │ ├── auth.types.ts │ │ └── document.types.ts │ ├── main.tsx │ ├── components │ │ ├── ui │ │ │ ├── skeleton.tsx │ │ │ ├── label.tsx │ │ │ ├── separator.tsx │ │ │ ├── textarea.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── input.tsx │ │ │ ├── sonner.tsx │ │ │ ├── badge.tsx │ │ │ ├── alert.tsx │ │ │ ├── tooltip.tsx │ │ │ ├── tabs.tsx │ │ │ ├── resizable.tsx │ │ │ ├── button.tsx │ │ │ ├── card.tsx │ │ │ ├── default-bar-chart.tsx │ │ │ ├── table.tsx │ │ │ ├── rounded-pie-chart.tsx │ │ │ ├── dialog.tsx │ │ │ └── sheet.tsx │ │ └── app │ │ │ ├── layout │ │ │ ├── github-icon.tsx │ │ │ ├── site-header.tsx │ │ │ └── nav-main.tsx │ │ │ ├── dashbaord │ │ │ ├── projects.tsx │ │ │ ├── recent-documents.tsx │ │ │ └── status-chart.tsx │ │ │ ├── user │ │ │ ├── users-table.tsx │ │ │ └── service-accounts-table.tsx │ │ │ ├── user-org │ │ │ ├── add-user-form.tsx │ │ │ └── organization-users-table.tsx │ │ │ └── loaders │ │ │ └── table-skeleton.tsx │ ├── vite-env.d.ts │ ├── hooks │ │ ├── use-organization.ts │ │ ├── use-query.ts │ │ ├── use-project.ts │ │ └── use-mobile.ts │ ├── lib │ │ ├── utils.ts │ │ ├── blob.ts │ │ └── auth.ts │ ├── axios.ts │ ├── layouts │ │ └── layout.tsx │ ├── App.tsx │ ├── contexts │ │ ├── ThemeContext.tsx │ │ └── AuthContext.tsx │ ├── assets │ │ ├── LlamaLogo.tsx │ │ └── react.svg │ ├── pages │ │ ├── login.tsx │ │ └── signup.tsx │ └── index.css ├── tsconfig.json ├── entrypoint.sh ├── Dockerfile.dev ├── .gitignore ├── vite.config.ts ├── index.html ├── components.json ├── tsconfig.node.json ├── eslint.config.js ├── tsconfig.app.json ├── Dockerfile ├── nginx.conf ├── README.md └── package.json ├── cmd.sh ├── entrypoint.sh ├── .gitignore ├── k8s └── charts │ └── llama-pg │ ├── .helmignore │ ├── charts │ ├── api │ │ ├── .helmignore │ │ ├── templates │ │ │ ├── service.yaml │ │ │ ├── serviceaccount.yaml │ │ │ ├── tests │ │ │ │ └── test-connection.yaml │ │ │ ├── configmap.yaml │ │ │ ├── secrets.yaml │ │ │ ├── hpa.yaml │ │ │ ├── ingress.yaml │ │ │ ├── NOTES.txt │ │ │ ├── _helpers.tpl │ │ │ └── deployment.yaml │ │ └── Chart.yaml │ └── worker │ │ ├── .helmignore │ │ ├── templates │ │ ├── service.yaml │ │ ├── serviceaccount.yaml │ │ ├── tests │ │ │ └── test-connection.yaml │ │ ├── configmap.yaml │ │ ├── secrets.yaml │ │ ├── hpa.yaml │ │ ├── ingress.yaml │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ └── deployment.yaml │ │ └── Chart.yaml │ ├── templates │ ├── serviceaccount.yaml │ ├── service.yaml │ ├── tests │ │ └── test-connection.yaml │ ├── configmap.yaml │ ├── secrets.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── NOTES.txt │ ├── _helpers.tpl │ └── deployment.yaml │ ├── Chart.lock │ └── Chart.yaml ├── pyproject.toml ├── healthcheck.sh ├── init_psql.sql ├── .github └── workflows │ └── continuous-integration.yaml ├── Makefile ├── LICENSE ├── Dockerfile ├── docker-compose.yml └── docker-compose-dev.yml /src/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.12 -------------------------------------------------------------------------------- /src/models/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/endpoints/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /frontend/.env.copy: -------------------------------------------------------------------------------- 1 | VITE_API_URL = "" -------------------------------------------------------------------------------- /tests/test_sample.py: -------------------------------------------------------------------------------- 1 | def test_sample(): 2 | assert True 3 | -------------------------------------------------------------------------------- /cmd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | uvicorn src.server:app --host 0.0.0.0 --port ${API_PORT:-8000} -------------------------------------------------------------------------------- /frontend/public/interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akvnn/llama-pg/HEAD/frontend/public/interface.png -------------------------------------------------------------------------------- /frontend/.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | Dockerfile 4 | .dockerignore 5 | .git 6 | .gitignore 7 | .env -------------------------------------------------------------------------------- /frontend/src/types/message.types.ts: -------------------------------------------------------------------------------- 1 | export interface Message { 2 | role: "user" | "assistant"; 3 | content: string; 4 | } 5 | -------------------------------------------------------------------------------- /entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o pipefail 5 | set -o nounset 6 | 7 | echo "entrypoint.sh is empty" 8 | 9 | exec "$@" 10 | -------------------------------------------------------------------------------- /src/constant.py: -------------------------------------------------------------------------------- 1 | class TableNames: 2 | reserved_project_table_name = "project" 3 | reserved_document_table_name = "document" 4 | reserved_pgai_table_name = "pgai" 5 | -------------------------------------------------------------------------------- /frontend/src/types/theme.types.ts: -------------------------------------------------------------------------------- 1 | export type Theme = "light" | "dark"; 2 | 3 | export interface ThemeContextType { 4 | theme: Theme; 5 | toggleTheme: () => void; 6 | setTheme: (theme: Theme) => void; 7 | } 8 | -------------------------------------------------------------------------------- /frontend/src/types/search.types.ts: -------------------------------------------------------------------------------- 1 | export interface SearchResult { 2 | id: string; 3 | title: string; 4 | metadata: Record; 5 | text: string; 6 | project_id: string; 7 | chunk: number; 8 | distance: number; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/src/types/user.types.ts: -------------------------------------------------------------------------------- 1 | export interface User { 2 | id: string; 3 | username: string; 4 | } 5 | 6 | export interface ServiceAccount { 7 | user_id: string; 8 | username: string; 9 | role: string; 10 | joined_at: string; 11 | } 12 | -------------------------------------------------------------------------------- /frontend/src/types/api.types.ts: -------------------------------------------------------------------------------- 1 | export interface PaginationResponse { 2 | items: T[]; 3 | total_count: number; 4 | page: number; 5 | per_page: number; 6 | total_pages: number; 7 | has_next: boolean; 8 | has_previous: boolean; 9 | } 10 | -------------------------------------------------------------------------------- /frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": [], 3 | "references": [ 4 | { "path": "./tsconfig.app.json" }, 5 | { "path": "./tsconfig.node.json" } 6 | ], 7 | "compilerOptions": { 8 | "baseUrl": ".", 9 | "paths": { 10 | "@/*": ["./src/*"] 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/types/org.types.ts: -------------------------------------------------------------------------------- 1 | export interface Organization { 2 | id: string; 3 | name: string; 4 | joined_at: string; 5 | role: string; 6 | } 7 | 8 | export interface OrganizationUser { 9 | user_id: string; 10 | username: string; 11 | role: string; 12 | joined_at: string; 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/main.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from "react-dom/client"; 2 | import "./index.css"; 3 | import App from "./App.tsx"; 4 | import { BrowserRouter } from "react-router-dom"; 5 | 6 | createRoot(document.getElementById("root")!).render( 7 | 8 | 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /frontend/src/types/dashboard.types.ts: -------------------------------------------------------------------------------- 1 | import type { LucideIcon } from "lucide-react"; 2 | 3 | export interface StatInfo { 4 | total_count: number; 5 | projects_count: number; 6 | status_counts: Record; 7 | } 8 | 9 | export interface Cards { 10 | title: string; 11 | badge: LucideIcon; 12 | } 13 | -------------------------------------------------------------------------------- /frontend/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cat > /usr/share/nginx/html/env.js <) { 4 | return ( 5 |
10 | ) 11 | } 12 | 13 | export { Skeleton } 14 | -------------------------------------------------------------------------------- /frontend/src/types/project.types.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const projectSchema = z.object({ 4 | project_id: z.string(), 5 | project_name: z.string(), 6 | number_of_documents: z.number(), 7 | created_at: z.string().nullable(), 8 | description: z.string().nullable(), 9 | }); 10 | 11 | export type Project = z.infer; 12 | -------------------------------------------------------------------------------- /frontend/Dockerfile.dev: -------------------------------------------------------------------------------- 1 | FROM node:22 2 | 3 | WORKDIR /app 4 | 5 | # Install dependencies 6 | COPY package.json package-lock.json* ./ 7 | RUN npm install 8 | 9 | # Copy source code 10 | COPY . . 11 | 12 | # Expose Vite dev server port 13 | EXPOSE 5173 14 | 15 | # Start development server with hot reload 16 | CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0", "--port", "5173"] -------------------------------------------------------------------------------- /frontend/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | interface ImportMetaEnv { 4 | readonly VITE_API_KEY: string; 5 | } 6 | 7 | interface ImportMeta { 8 | readonly env: ImportMetaEnv; 9 | } 10 | 11 | declare global { 12 | interface Window { 13 | VITE_API_URL: string; 14 | VITE_JWT_EXPIRES_IN: number; 15 | } 16 | } 17 | 18 | export {}; 19 | -------------------------------------------------------------------------------- /frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | .env 16 | 17 | # Editor directories and files 18 | .vscode/* 19 | !.vscode/extensions.json 20 | .idea 21 | .DS_Store 22 | *.suo 23 | *.ntvs* 24 | *.njsproj 25 | *.sln 26 | *.sw? 27 | -------------------------------------------------------------------------------- /frontend/vite.config.ts: -------------------------------------------------------------------------------- 1 | import path from "path" 2 | import { defineConfig } from 'vite' 3 | import react from '@vitejs/plugin-react' 4 | import tailwindcss from '@tailwindcss/vite' 5 | 6 | // https://vite.dev/config/ 7 | export default defineConfig({ 8 | plugins: [react(),tailwindcss()], 9 | resolve: { 10 | alias: { 11 | "@": path.resolve(__dirname, "./src"), 12 | }, 13 | }, 14 | }) 15 | -------------------------------------------------------------------------------- /src/server.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | import uvicorn 3 | from fastapi import FastAPI 4 | from src.main import create_app 5 | from src.configuration import config 6 | 7 | warnings.filterwarnings("ignore", category=UserWarning, message=".*validate_default.*") 8 | 9 | app: FastAPI = create_app() 10 | 11 | if __name__ == "__main__": 12 | uvicorn.run("src.server:app", host="0.0.0.0", port=config.API_PORT, reload=True) 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python-generated files 2 | __pycache__/ 3 | *.py[oc] 4 | build/ 5 | dist/ 6 | wheels/ 7 | *.egg-info 8 | .ruff_cache/ 9 | .idea/ 10 | 11 | # Virtual environments 12 | .venv 13 | .vscode 14 | 15 | # Environment variables 16 | .env 17 | venv/ 18 | 19 | # Logs 20 | *.log 21 | 22 | # Data 23 | pgdata/ 24 | */pdf_documents/ 25 | *.pdf 26 | 27 | # Misc 28 | manual*.py 29 | 30 | # Charts 31 | k8s/charts/*/charts/*.tgz -------------------------------------------------------------------------------- /frontend/src/types/auth.types.ts: -------------------------------------------------------------------------------- 1 | export interface AuthUser { 2 | username: string; 3 | userOrgIds: string[]; 4 | } 5 | 6 | export interface AuthContextType { 7 | isAuthenticated: boolean; 8 | user: AuthUser | null; 9 | loading: boolean; 10 | handleLogin: (username: string, password: string) => Promise; 11 | handleSignup: (username: string, password: string) => Promise; 12 | handleLogout: () => void; 13 | } 14 | -------------------------------------------------------------------------------- /frontend/src/hooks/use-organization.ts: -------------------------------------------------------------------------------- 1 | import { create } from "zustand"; 2 | 3 | interface OrganizationStore { 4 | currentOrganization: string | null; 5 | setCurrentOrganization: (org: string | null) => void; 6 | } 7 | 8 | export const useOrganizationStore = create((set) => ({ 9 | currentOrganization: null, 10 | setCurrentOrganization: (org: string | null) => 11 | set({ currentOrganization: org }), 12 | })); 13 | -------------------------------------------------------------------------------- /src/models/system.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from pydantic import BaseModel 3 | from typing import Dict 4 | 5 | 6 | class ErrorInfo(BaseModel): 7 | message: str 8 | details: Dict[str, str] 9 | recorded_at: datetime.datetime 10 | 11 | 12 | class StatInfo(BaseModel): 13 | total_count: int 14 | projects_count: int 15 | status_counts: Dict[str, int] 16 | 17 | 18 | class SystemResponse(BaseModel): 19 | items: list[ErrorInfo] 20 | -------------------------------------------------------------------------------- /frontend/src/hooks/use-query.ts: -------------------------------------------------------------------------------- 1 | import { use } from "react"; 2 | 3 | const promiseCache = new Map>(); 4 | export function useQuery({ 5 | fn, 6 | key, 7 | }: { 8 | fn: () => Promise; 9 | key: string; 10 | }) { 11 | if (!promiseCache.has(key)) promiseCache.set(key, fn()); 12 | 13 | const promise = promiseCache.get(key) as Promise; 14 | const result = use(promise); 15 | 16 | return result; 17 | } 18 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/api/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/api/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "api.fullname" . }} 5 | labels: 6 | {{- include "api.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: {{ .Values.service.targetPort }} 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "api.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/api/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "api.serviceAccountName" . }} 6 | labels: 7 | {{- include "api.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | automountServiceAccountToken: {{ .Values.serviceAccount.automount }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "llama-pg.serviceAccountName" . }} 6 | labels: 7 | {{- include "llama-pg.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | automountServiceAccountToken: {{ .Values.serviceAccount.automount }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /frontend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | LlamaPG 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/api/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "api.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "api.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "api.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/worker/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "llama-pg.fullname" . }} 5 | labels: 6 | {{- include "llama-pg.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: {{ .Values.service.targetPort }} 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "llama-pg.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/worker/templates/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "worker.fullname" . }} 5 | labels: 6 | {{- include "worker.labels" . | nindent 4 }} 7 | spec: 8 | type: {{ .Values.service.type }} 9 | ports: 10 | - port: {{ .Values.service.port }} 11 | targetPort: {{ .Values.service.targetPort }} 12 | protocol: TCP 13 | name: http 14 | selector: 15 | {{- include "worker.selectorLabels" . | nindent 4 }} 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/worker/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "worker.serviceAccountName" . }} 6 | labels: 7 | {{- include "worker.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | automountServiceAccountToken: {{ .Values.serviceAccount.automount }} 13 | {{- end }} 14 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "llama-pg.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "llama-pg.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "llama-pg.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/worker/templates/tests/test-connection.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: "{{ include "worker.fullname" . }}-test-connection" 5 | labels: 6 | {{- include "worker.labels" . | nindent 4 }} 7 | annotations: 8 | "helm.sh/hook": test 9 | spec: 10 | containers: 11 | - name: wget 12 | image: busybox 13 | command: ['wget'] 14 | args: ['{{ include "worker.fullname" . }}:{{ .Values.service.port }}'] 15 | restartPolicy: Never 16 | -------------------------------------------------------------------------------- /frontend/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx"; 2 | import { twMerge } from "tailwind-merge"; 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)); 6 | } 7 | 8 | export function formatDate(dateStr: string): string { 9 | const date = new Date(dateStr); 10 | if (isNaN(date.getTime())) return "Invalid date"; 11 | 12 | return date.toLocaleDateString("en-UK", { 13 | day: "numeric", 14 | month: "numeric", 15 | year: "numeric", 16 | }); 17 | } 18 | -------------------------------------------------------------------------------- /src/models/project.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | from pydantic import BaseModel 3 | 4 | 5 | class ProjectRequest(BaseModel): 6 | organization_id: str 7 | project_name: str 8 | project_description: str 9 | 10 | 11 | class ProjectInfo(BaseModel): 12 | project_id: str 13 | project_name: str 14 | number_of_documents: int 15 | created_at: datetime.datetime | None = None 16 | updated_at: datetime.datetime | None = None 17 | description: str | None = None 18 | created_by_user_id: str | None = None 19 | -------------------------------------------------------------------------------- /frontend/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "", 8 | "css": "src/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | }, 20 | "iconLibrary": "lucide" 21 | } -------------------------------------------------------------------------------- /k8s/charts/llama-pg/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: api 3 | repository: file://charts/api 4 | version: 0.1.0 5 | - name: worker 6 | repository: file://charts/worker 7 | version: 0.1.0 8 | - name: redis-ha 9 | repository: https://dandydeveloper.github.io/charts 10 | version: 4.35.2 11 | - name: timescaledb 12 | repository: https://akvnn.github.io/helm-timescaledb 13 | version: 0.1.1 14 | digest: sha256:3d71fbee2fb102bdb6719237695f858a96439d5335d73923fcb601c17aaddab8 15 | generated: "2025-11-05T11:48:01.7073458+04:00" 16 | -------------------------------------------------------------------------------- /src/depedency.py: -------------------------------------------------------------------------------- 1 | from fastapi import Request 2 | 3 | 4 | async def settings_provider(request: Request): 5 | yield request.app.settings 6 | 7 | 8 | async def get_db_pool(request: Request): 9 | return request.app.pool 10 | 11 | 12 | async def get_worker_client(request: Request): 13 | return request.app.worker_client 14 | 15 | 16 | async def get_pgai_client(request: Request): 17 | return request.app.pgai_client 18 | 19 | 20 | async def get_parser_client(request: Request): 21 | return request.app.parser_client 22 | -------------------------------------------------------------------------------- /frontend/src/axios.ts: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | import { getToken } from "./lib/auth"; 3 | 4 | const axiosInstance = axios.create({ 5 | baseURL: window.VITE_API_URL || "http://localhost:8000", 6 | }); 7 | 8 | axiosInstance.interceptors.request.use( 9 | (config) => { 10 | const token = getToken(); 11 | if (token) { 12 | config.headers.Authorization = `Bearer ${token}`; 13 | } 14 | return config; 15 | }, 16 | (error) => { 17 | return Promise.reject(error); 18 | } 19 | ); 20 | 21 | export default axiosInstance; 22 | -------------------------------------------------------------------------------- /frontend/src/hooks/use-project.ts: -------------------------------------------------------------------------------- 1 | import { create } from "zustand"; 2 | import { persist } from "zustand/middleware"; 3 | 4 | interface ProjectStore { 5 | currentProject: string | null; 6 | setCurrentProject: (projectId: string | null) => void; 7 | } 8 | 9 | export const useProjectStore = create()( 10 | persist( 11 | (set) => ({ 12 | currentProject: null, 13 | setCurrentProject: (projectId) => set({ currentProject: projectId }), 14 | }), 15 | { 16 | name: "project-storage", 17 | } 18 | ) 19 | ); 20 | -------------------------------------------------------------------------------- /frontend/src/components/app/layout/github-icon.tsx: -------------------------------------------------------------------------------- 1 | import { Button } from "@/components/ui/button"; 2 | import { Github } from "lucide-react"; 3 | 4 | export default function GithubIcon() { 5 | return ( 6 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/api/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "api.fullname" . }}-config 5 | labels: 6 | app.kubernetes.io/name: {{ include "api.name" . }} 7 | helm.sh/chart: {{ include "api.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | data: 11 | {{- if .Values.configMapEnv }} 12 | {{- range $key, $val := .Values.configMapEnv }} 13 | {{ $key }}: {{ $val | quote }} 14 | {{- end }} 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "llama-pg.fullname" . }}-config 5 | labels: 6 | app.kubernetes.io/name: {{ include "llama-pg.name" . }} 7 | helm.sh/chart: {{ include "llama-pg.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | data: 11 | {{- if .Values.configMapEnv }} 12 | {{- range $key, $val := .Values.configMapEnv }} 13 | {{ $key }}: {{ $val | quote }} 14 | {{- end }} 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/api/templates/secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ include "api.fullname" . }}-secret 5 | labels: 6 | app.kubernetes.io/name: {{ include "api.name" . }} 7 | helm.sh/chart: {{ include "api.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | type: Opaque 11 | data: 12 | {{- if .Values.secretEnv }} 13 | {{- range $key, $val := .Values.secretEnv }} 14 | {{ $key }}: {{ $val | quote }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/worker/templates/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: {{ include "worker.fullname" . }}-config 5 | labels: 6 | app.kubernetes.io/name: {{ include "worker.name" . }} 7 | helm.sh/chart: {{ include "worker.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | data: 11 | {{- if .Values.configMapEnv }} 12 | {{- range $key, $val := .Values.configMapEnv }} 13 | {{ $key }}: {{ $val | quote }} 14 | {{- end }} 15 | {{- end }} 16 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/templates/secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ include "llama-pg.fullname" . }}-secret 5 | labels: 6 | app.kubernetes.io/name: {{ include "llama-pg.name" . }} 7 | helm.sh/chart: {{ include "llama-pg.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | type: Opaque 11 | data: 12 | {{- if .Values.secretEnv }} 13 | {{- range $key, $val := .Values.secretEnv }} 14 | {{ $key }}: {{ $val | quote }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/charts/worker/templates/secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ include "worker.fullname" . }}-secret 5 | labels: 6 | app.kubernetes.io/name: {{ include "worker.name" . }} 7 | helm.sh/chart: {{ include "worker.chart" . }} 8 | app.kubernetes.io/instance: {{ .Release.Name }} 9 | app.kubernetes.io/managed-by: {{ .Release.Service }} 10 | type: Opaque 11 | data: 12 | {{- if .Values.secretEnv }} 13 | {{- range $key, $val := .Values.secretEnv }} 14 | {{ $key }}: {{ $val | quote }} 15 | {{- end }} 16 | {{- end }} 17 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "llama-pg" 3 | version = "0.1.0" 4 | description = "RaaS orchestrator" 5 | readme = "README.md" 6 | requires-python = ">=3.12" 7 | dependencies = [ 8 | "arq==0.26.3", 9 | "bcrypt>=5.0.0", 10 | "fastapi==0.110.1", 11 | "llama-cloud-services>=0.6.76", 12 | "loguru==0.7.3", 13 | "numpy==2.2.6", 14 | "openai==1.82.1", 15 | "pgai[vectorizer-worker]>=0.12.1", 16 | "psycopg-pool==3.2.6", 17 | "psycopg2-binary==2.9.9", 18 | "python-multipart>=0.0.20", 19 | "uvicorn==0.29.0", 20 | ] 21 | 22 | [dependency-groups] 23 | dev = [ 24 | "ruff>=0.12.0", 25 | ] 26 | -------------------------------------------------------------------------------- /frontend/src/hooks/use-mobile.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | const MOBILE_BREAKPOINT = 768 4 | 5 | export function useIsMobile() { 6 | const [isMobile, setIsMobile] = React.useState(undefined) 7 | 8 | React.useEffect(() => { 9 | const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 | const onChange = () => { 11 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 | } 13 | mql.addEventListener("change", onChange) 14 | setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 | return () => mql.removeEventListener("change", onChange) 16 | }, []) 17 | 18 | return !!isMobile 19 | } 20 | -------------------------------------------------------------------------------- /healthcheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PORT=${1:-8000} 4 | TIMEOUT=5 # Lower timeout for curl requests 5 | 6 | echo "Checking health on port: $PORT" 7 | 8 | # Use timeout flag with curl to prevent hanging 9 | http_response=$(curl --max-time $TIMEOUT -s -o /dev/null -w "%{http_code}" http://localhost:$PORT/health || echo "000") 10 | 11 | if [ "$http_response" = "500" ]; then 12 | echo "Health check failed: Server error (HTTP 500) on port $PORT" 13 | exit 1 14 | elif [ "$http_response" = "000" ]; then 15 | echo "Health check failed: Server unreachable or connection timeout on port $PORT" 16 | exit 1 17 | fi 18 | 19 | echo "Service on port $PORT is healthy (HTTP $http_response)" 20 | exit 0 -------------------------------------------------------------------------------- /frontend/src/components/ui/label.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | import * as LabelPrimitive from "@radix-ui/react-label" 3 | 4 | import { cn } from "@/lib/utils" 5 | 6 | function Label({ 7 | className, 8 | ...props 9 | }: React.ComponentProps) { 10 | return ( 11 | 19 | ) 20 | } 21 | 22 | export { Label } 23 | -------------------------------------------------------------------------------- /k8s/charts/llama-pg/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: llama-pg 3 | description: A Helm chart for llama-pg RaaS orchestrator 4 | type: application 5 | version: 0.1.3 6 | appVersion: "0.1.3" 7 | dependencies: 8 | - name: api 9 | version: "0.1.3" 10 | repository: file://charts/api 11 | - name: worker 12 | version: "0.1.3" 13 | repository: file://charts/worker 14 | condition: worker.enabled 15 | - name: redis-ha 16 | version: "4.35.2" 17 | repository: https://dandydeveloper.github.io/charts 18 | condition: worker.enabled && worker.redis.enabled 19 | - name: timescaledb 20 | version: "0.1.1" 21 | repository: https://akvnn.github.io/helm-timescaledb 22 | condition: timescaledb.enabled -------------------------------------------------------------------------------- /frontend/public/llama-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /frontend/tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 | "target": "ES2022", 5 | "lib": ["ES2023"], 6 | "module": "ESNext", 7 | "skipLibCheck": true, 8 | 9 | /* Bundler mode */ 10 | "moduleResolution": "bundler", 11 | "allowImportingTsExtensions": true, 12 | "verbatimModuleSyntax": true, 13 | "moduleDetection": "force", 14 | "noEmit": true, 15 | 16 | /* Linting */ 17 | "strict": true, 18 | "noUnusedLocals": true, 19 | "noUnusedParameters": true, 20 | "erasableSyntaxOnly": true, 21 | "noFallthroughCasesInSwitch": true, 22 | "noUncheckedSideEffectImports": true 23 | }, 24 | "include": ["vite.config.ts"] 25 | } 26 | -------------------------------------------------------------------------------- /init_psql.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE IF NOT EXISTS users ( 2 | id UUID PRIMARY KEY DEFAULT gen_random_uuid(), 3 | username TEXT UNIQUE NOT NULL, 4 | password_hash TEXT NOT NULL, 5 | is_service_account BOOLEAN DEFAULT FALSE, 6 | created_at TIMESTAMPTZ DEFAULT NOW(), 7 | last_login TIMESTAMPTZ 8 | ); 9 | 10 | CREATE TABLE IF NOT EXISTS organizations ( 11 | id UUID PRIMARY KEY DEFAULT gen_random_uuid(), 12 | name TEXT NOT NULL, 13 | created_at TIMESTAMPTZ DEFAULT NOW() 14 | ); 15 | 16 | CREATE TABLE IF NOT EXISTS user_org ( 17 | id UUID PRIMARY KEY DEFAULT gen_random_uuid(), 18 | user_id UUID REFERENCES users(id) ON DELETE CASCADE, 19 | org_id UUID REFERENCES organizations(id) ON DELETE CASCADE, 20 | role TEXT NOT NULL, 21 | joined_at TIMESTAMPTZ DEFAULT NOW() 22 | ); 23 | -------------------------------------------------------------------------------- /frontend/src/components/ui/separator.tsx: -------------------------------------------------------------------------------- 1 | "use client" 2 | 3 | import * as React from "react" 4 | import * as SeparatorPrimitive from "@radix-ui/react-separator" 5 | 6 | import { cn } from "@/lib/utils" 7 | 8 | function Separator({ 9 | className, 10 | orientation = "horizontal", 11 | decorative = true, 12 | ...props 13 | }: React.ComponentProps) { 14 | return ( 15 | 25 | ) 26 | } 27 | 28 | export { Separator } 29 | -------------------------------------------------------------------------------- /frontend/src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 | return ( 7 |