- {article.content} -
-diff --git a/.assets/manifest.json b/.assets/manifest.json deleted file mode 100644 index e69de29..0000000 diff --git a/.assets/perplexica-screenshot.png b/.assets/perplexica-screenshot.png index fc7a697..c47a544 100644 Binary files a/.assets/perplexica-screenshot.png and b/.assets/perplexica-screenshot.png differ diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..1c735cc --- /dev/null +++ b/.env.example @@ -0,0 +1,5 @@ +PORT=3001 +OLLAMA_URL=http://localhost:11434 # url of the ollama server +SIMILARITY_MEASURE=cosine # cosine or dot +SEARXNG_API_URL= # no need to fill this if using docker +MODEL_NAME=llama2 \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 1de1177..e065bb4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -4,6 +4,7 @@ about: Create an issue to help us fix bugs title: '' labels: bug assignees: '' + --- **Describe the bug** @@ -11,7 +12,6 @@ A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: - 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md index 96a4735..48d5f81 100644 --- a/.github/ISSUE_TEMPLATE/custom.md +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -4,4 +4,7 @@ about: Describe this issue template's purpose here. title: '' labels: '' assignees: '' + --- + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 5f0a04c..11fc491 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -4,6 +4,7 @@ about: Suggest an idea for this project title: '' labels: enhancement assignees: '' + --- **Is your feature request related to a problem? Please describe.** diff --git a/.github/workflows/docker-build.yaml b/.github/workflows/docker-build.yaml deleted file mode 100644 index 29f7987..0000000 --- a/.github/workflows/docker-build.yaml +++ /dev/null @@ -1,138 +0,0 @@ -name: Build & Push Docker Images - -on: - push: - branches: - - master - release: - types: [published] - -jobs: - build-amd64: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - install: true - - - name: Log in to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract version from release tag - if: github.event_name == 'release' - id: version - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - - name: Build and push AMD64 Docker image - if: github.ref == 'refs/heads/master' && github.event_name == 'push' - run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica - docker buildx build --platform linux/amd64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:amd64 \ - --cache-to=type=inline \ - --provenance false \ - -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:amd64 \ - --push . - - - name: Build and push AMD64 release Docker image - if: github.event_name == 'release' - run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica - docker buildx build --platform linux/amd64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-amd64 \ - --cache-to=type=inline \ - --provenance false \ - -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-amd64 \ - --push . - - build-arm64: - runs-on: ubuntu-24.04-arm - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - install: true - - - name: Log in to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract version from release tag - if: github.event_name == 'release' - id: version - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - - name: Build and push ARM64 Docker image - if: github.ref == 'refs/heads/master' && github.event_name == 'push' - run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica - docker buildx build --platform linux/arm64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:arm64 \ - --cache-to=type=inline \ - --provenance false \ - -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:arm64 \ - --push . - - - name: Build and push ARM64 release Docker image - if: github.event_name == 'release' - run: | - DOCKERFILE=app.dockerfile - IMAGE_NAME=perplexica - docker buildx build --platform linux/arm64 \ - --cache-from=type=registry,ref=itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-arm64 \ - --cache-to=type=inline \ - --provenance false \ - -f $DOCKERFILE \ - -t itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-arm64 \ - --push . - - manifest: - needs: [build-amd64, build-arm64] - runs-on: ubuntu-latest - steps: - - name: Log in to DockerHub - uses: docker/login-action@v2 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract version from release tag - if: github.event_name == 'release' - id: version - run: echo "RELEASE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV - - - name: Create and push multi-arch manifest for main - if: github.ref == 'refs/heads/master' && github.event_name == 'push' - run: | - IMAGE_NAME=perplexica - docker manifest create itzcrazykns1337/${IMAGE_NAME}:main \ - --amend itzcrazykns1337/${IMAGE_NAME}:amd64 \ - --amend itzcrazykns1337/${IMAGE_NAME}:arm64 - docker manifest push itzcrazykns1337/${IMAGE_NAME}:main - - - name: Create and push multi-arch manifest for releases - if: github.event_name == 'release' - run: | - IMAGE_NAME=perplexica - docker manifest create itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }} \ - --amend itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-amd64 \ - --amend itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }}-arm64 - docker manifest push itzcrazykns1337/${IMAGE_NAME}:${{ env.RELEASE_VERSION }} diff --git a/.gitignore b/.gitignore index 9fb5e4c..0f857e0 100644 --- a/.gitignore +++ b/.gitignore @@ -4,9 +4,8 @@ npm-debug.log yarn-error.log # Build output -.next/ -out/ -dist/ +/.next/ +/out/ # IDE/Editor specific .vscode/ @@ -20,9 +19,6 @@ dist/ .env.test.local .env.production.local -# Config files -config.toml - # Log files logs/ *.log @@ -32,10 +28,4 @@ logs/ # Miscellaneous .DS_Store -Thumbs.db - -# Db -db.sqlite -/searxng - -certificates \ No newline at end of file +Thumbs.db \ No newline at end of file diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index 55d3c7c..0000000 --- a/.prettierignore +++ /dev/null @@ -1,41 +0,0 @@ -# Ignore all files in the node_modules directory -node_modules - -# Ignore all files in the .next directory (Next.js build output) -.next - -# Ignore all files in the .out directory (TypeScript build output) -.out - -# Ignore all files in the .cache directory (Prettier cache) -.cache - -# Ignore all files in the .vscode directory (Visual Studio Code settings) -.vscode - -# Ignore all files in the .idea directory (IntelliJ IDEA settings) -.idea - -# Ignore all files in the dist directory (build output) -dist - -# Ignore all files in the build directory (build output) -build - -# Ignore all files in the coverage directory (test coverage reports) -coverage - -# Ignore all files with the .log extension -*.log - -# Ignore all files with the .tmp extension -*.tmp - -# Ignore all files with the .swp extension -*.swp - -# Ignore all files with the .DS_Store extension (macOS specific) -.DS_Store - -# Ignore all files in uploads directory -uploads \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js index 8ca480f..1937ff1 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -6,6 +6,7 @@ const config = { endOfLine: 'auto', singleQuote: true, tabWidth: 2, + semi: true, }; module.exports = config; diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7bbb280..af43ae1 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,43 +1,32 @@ # How to Contribute to Perplexica -Thanks for your interest in contributing to Perplexica! Your help makes this project better. This guide explains how to contribute effectively. - -Perplexica is a modern AI chat application with advanced search capabilities. +Hey there, thanks for deciding to contribute to Perplexica. Anything you help with will support the development of Perplexica and will make it better. Let's walk you through the key aspects to ensure your contributions are effective and in harmony with the project's setup. ## Project Structure -Perplexica's codebase is organized as follows: +Perplexica's design consists of two main domains: -- **UI Components and Pages**: - - **Components (`src/components`)**: Reusable UI components. - - **Pages and Routes (`src/app`)**: Next.js app directory structure with page components. - - Main app routes include: home (`/`), chat (`/c`), discover (`/discover`), library (`/library`), and settings (`/settings`). - - **API Routes (`src/app/api`)**: API endpoints implemented with Next.js API routes. - - `/api/chat`: Handles chat interactions. - - `/api/search`: Provides direct access to Perplexica's search capabilities. - - Other endpoints for models, files, and suggestions. -- **Backend Logic (`src/lib`)**: Contains all the backend functionality including search, database, and API logic. - - The search functionality is present inside `src/lib/search` directory. - - All of the focus modes are implemented using the Meta Search Agent class in `src/lib/search/metaSearchAgent.ts`. - - Database functionality is in `src/lib/db`. - - Chat model and embedding model providers are managed in `src/lib/providers`. - - Prompt templates and LLM chain definitions are in `src/lib/prompts` and `src/lib/chains` respectively. +- **Frontend (`ui` directory)**: This is a Next.js application holding all user interface components. It's a self-contained environment that manages everything the user interacts with. +- **Backend (root and `src` directory)**: The backend logic is situated in the `src` folder, but the root directory holds the main `package.json` for backend dependency management. -## API Documentation - -Perplexica exposes several API endpoints for programmatic access, including: - -- **Search API**: Access Perplexica's advanced search capabilities directly via the `/api/search` endpoint. For detailed documentation, see `docs/api/search.md`. +Both the root directory (for backend configurations outside `src`) and the `ui` folder come with an `.env.example` file. These are templates for environment variables that you need to set up manually for the application to run correctly. ## Setting Up Your Environment Before diving into coding, setting up your local environment is key. Here's what you need to do: -1. In the root directory, locate the `sample.config.toml` file. -2. Rename it to `config.toml` and fill in the necessary configuration fields. -3. Run `npm install` to install all dependencies. -4. Run `npm run db:push` to set up the local sqlite database. -5. Use `npm run dev` to start the application in development mode. +### Backend + +1. In the root directory, locate the `.env.example` file. +2. Rename it to `.env` and fill in the necessary environment variables specific to the backend. +3. Run `npm install` to install dependencies. +4. Use `npm run dev` to start the backend in development mode. + +### Frontend + +1. Navigate to the `ui` folder and repeat the process of renaming `.env.example` to `.env`, making sure to provide the frontend-specific variables. +2. Execute `npm install` within the `ui` directory to get the frontend dependencies ready. +3. Launch the frontend development server with `npm run dev`. **Please note**: Docker configurations are present for setting up production environments, whereas `npm run dev` is used for development purposes. diff --git a/README.md b/README.md index 5eb0713..562bd65 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,6 @@ # 🚀 Perplexica - An AI-powered search engine 🔎 -
- {item.content.slice(0, 100)}... -
-- No chats found. -
-- {formatTimeDifference(new Date(), chat.createdAt)} Ago -
-- Theme -
-- Measurement Units -
-- Automatic Image Search -
-- Automatically search for relevant images in chat - responses -
-- Automatic Video Search -
-- Automatically search for relevant videos in chat - responses -
-- Chat Model Provider -
-- Chat Model -
-- Model Name -
- ) => { - setConfig((prev) => ({ - ...prev!, - customOpenaiModelName: e.target.value, - })); - }} - onSave={(value) => - saveConfig('customOpenaiModelName', value) - } - /> -- Custom OpenAI API Key -
- ) => { - setConfig((prev) => ({ - ...prev!, - customOpenaiApiKey: e.target.value, - })); - }} - onSave={(value) => - saveConfig('customOpenaiApiKey', value) - } - /> -- Custom OpenAI Base URL -
- ) => { - setConfig((prev) => ({ - ...prev!, - customOpenaiApiUrl: e.target.value, - })); - }} - onSave={(value) => - saveConfig('customOpenaiApiUrl', value) - } - /> -- Embedding Model Provider -
-- Embedding Model -
-- OpenAI API Key -
- { - setConfig((prev) => ({ - ...prev!, - openaiApiKey: e.target.value, - })); - }} - onSave={(value) => saveConfig('openaiApiKey', value)} - /> -- Ollama API URL -
- { - setConfig((prev) => ({ - ...prev!, - ollamaApiUrl: e.target.value, - })); - }} - onSave={(value) => saveConfig('ollamaApiUrl', value)} - /> -- Ollama API Key (Can be left blank) -
- { - setConfig((prev) => ({ - ...prev!, - ollamaApiKey: e.target.value, - })); - }} - onSave={(value) => saveConfig('ollamaApiKey', value)} - /> -- GROQ API Key -
- { - setConfig((prev) => ({ - ...prev!, - groqApiKey: e.target.value, - })); - }} - onSave={(value) => saveConfig('groqApiKey', value)} - /> -- Anthropic API Key -
- { - setConfig((prev) => ({ - ...prev!, - anthropicApiKey: e.target.value, - })); - }} - onSave={(value) => saveConfig('anthropicApiKey', value)} - /> -- Gemini API Key -
- { - setConfig((prev) => ({ - ...prev!, - geminiApiKey: e.target.value, - })); - }} - onSave={(value) => saveConfig('geminiApiKey', value)} - /> -- Deepseek API Key -
- { - setConfig((prev) => ({ - ...prev!, - deepseekApiKey: e.target.value, - })); - }} - onSave={(value) => saveConfig('deepseekApiKey', value)} - /> -- AI/ML API Key -
- { - setConfig((prev) => ({ - ...prev!, - aimlApiKey: e.target.value, - })); - }} - onSave={(value) => saveConfig('aimlApiKey', value)} - /> -- LM Studio API URL -
- { - setConfig((prev) => ({ - ...prev!, - lmStudioApiUrl: e.target.value, - })); - }} - onSave={(value) => saveConfig('lmStudioApiUrl', value)} - /> -- Failed to connect to the server. Please try again later. -
-- {suggestion} -
-- Uploading.. -
-- {files.length} files -
- > - )} - - {files.length === 1 && ( - <> -- {files[0].fileName.length > 10 - ? files[0].fileName.replace(/\.\w+$/, '').substring(0, 3) + - '...' + - files[0].fileExtension - : files[0].fileName} -
- > - )} -- {file.fileName.length > 25 - ? file.fileName.replace(/\.\w+$/, '').substring(0, 25) + - '...' + - file.fileExtension - : file.fileName} -
-- {file.fileName.length > 25 - ? file.fileName.replace(/\.\w+$/, '').substring(0, 25) + - '...' + - file.fileExtension - : file.fileName} -
-setCopilotEnabled(!copilotEnabled)} - className={cn( - 'text-xs font-medium transition-colors duration-150 ease-in-out', - copilotEnabled - ? 'text-[#24A0ED]' - : 'text-black/50 dark:text-white/50 group-hover:text-black dark:group-hover:text-white', - )} - > - Copilot -
-- {focusModes.find((mode) => mode.key === focusMode)?.title} -
-Focus
-{mode.title}
-- {mode.description} -
-- { - OptimizationModes.find((mode) => mode.key === optimizationMode) - ?.title - } -
-{mode.title}
-- {mode.description} -
-- {source.metadata.title} -
-- {source.metadata.url.replace(/.+\/\/|www.|\..+/g, '')} -
-- {article.content} -
-