diff --git a/.env.example b/.env.example index b0a0f20b9fc..f2a51198f42 100644 --- a/.env.example +++ b/.env.example @@ -119,6 +119,7 @@ BINGAI_TOKEN=user_provided # BEDROCK_AWS_DEFAULT_REGION=us-east-1 # A default region must be provided # BEDROCK_AWS_ACCESS_KEY_ID=someAccessKey # BEDROCK_AWS_SECRET_ACCESS_KEY=someSecretAccessKey +# BEDROCK_AWS_SESSION_TOKEN=someSessionToken # Note: This example list is not meant to be exhaustive. If omitted, all known, supported model IDs will be included for you. # BEDROCK_AWS_MODELS=anthropic.claude-3-5-sonnet-20240620-v1:0,meta.llama3-1-8b-instruct-v1:0 @@ -137,10 +138,13 @@ BINGAI_TOKEN=user_provided #============# GOOGLE_KEY=user_provided + # GOOGLE_REVERSE_PROXY= +# Some reverse proxies do not support the X-goog-api-key header, uncomment to pass the API key in Authorization header instead. +# GOOGLE_AUTH_HEADER=true # Gemini API (AI Studio) -# GOOGLE_MODELS=gemini-1.5-flash-latest,gemini-1.0-pro,gemini-1.0-pro-001,gemini-1.0-pro-latest,gemini-1.0-pro-vision-latest,gemini-1.5-pro-latest,gemini-pro,gemini-pro-vision +# GOOGLE_MODELS=gemini-2.0-flash-exp,gemini-2.0-flash-thinking-exp-1219,gemini-exp-1121,gemini-exp-1114,gemini-1.5-flash-latest,gemini-1.0-pro,gemini-1.0-pro-001,gemini-1.0-pro-latest,gemini-1.0-pro-vision-latest,gemini-1.5-pro-latest,gemini-pro,gemini-pro-vision # Vertex AI # GOOGLE_MODELS=gemini-1.5-flash-preview-0514,gemini-1.5-pro-preview-0514,gemini-1.0-pro-vision-001,gemini-1.0-pro-002,gemini-1.0-pro-001,gemini-pro-vision,gemini-1.0-pro @@ -166,6 +170,7 @@ GOOGLE_KEY=user_provided # GOOGLE_SAFETY_HATE_SPEECH=BLOCK_ONLY_HIGH # GOOGLE_SAFETY_HARASSMENT=BLOCK_ONLY_HIGH # GOOGLE_SAFETY_DANGEROUS_CONTENT=BLOCK_ONLY_HIGH +# GOOGLE_SAFETY_CIVIC_INTEGRITY=BLOCK_ONLY_HIGH #============# # OpenAI # @@ -177,10 +182,10 @@ OPENAI_API_KEY=user_provided DEBUG_OPENAI=false # TITLE_CONVO=false -# OPENAI_TITLE_MODEL=gpt-3.5-turbo +# OPENAI_TITLE_MODEL=gpt-4o-mini # OPENAI_SUMMARIZE=true -# OPENAI_SUMMARY_MODEL=gpt-3.5-turbo +# OPENAI_SUMMARY_MODEL=gpt-4o-mini # OPENAI_FORCE_PROMPT=true @@ -352,6 +357,7 @@ ILLEGAL_MODEL_REQ_SCORE=5 #========================# CHECK_BALANCE=false +# START_BALANCE=20000 # note: the number of tokens that will be credited after registration. #========================# # Registration and Login # diff --git a/.eslintrc.js b/.eslintrc.js index cbb34c74f24..539c6426505 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,6 +18,10 @@ module.exports = { 'client/dist/**/*', 'client/public/**/*', 'e2e/playwright-report/**/*', + 'packages/mcp/types/**/*', + 'packages/mcp/dist/**/*', + 'packages/mcp/test_bundle/**/*', + 'api/demo/**/*', 'packages/data-provider/types/**/*', 'packages/data-provider/dist/**/*', 'packages/data-provider/test_bundle/**/*', @@ -136,6 +140,30 @@ module.exports = { }, ], }, + { + files: './api/demo/**/*.ts', + overrides: [ + { + files: '**/*.ts', + parser: '@typescript-eslint/parser', + parserOptions: { + project: './packages/data-provider/tsconfig.json', + }, + }, + ], + }, + { + files: './packages/mcp/**/*.ts', + overrides: [ + { + files: '**/*.ts', + parser: '@typescript-eslint/parser', + parserOptions: { + project: './packages/mcp/tsconfig.json', + }, + }, + ], + }, { files: './config/translations/**/*.ts', parser: '@typescript-eslint/parser', @@ -149,6 +177,18 @@ module.exports = { project: './packages/data-provider/tsconfig.spec.json', }, }, + { + files: ['./api/demo/specs/**/*.ts'], + parserOptions: { + project: './packages/data-provider/tsconfig.spec.json', + }, + }, + { + files: ['./packages/mcp/specs/**/*.ts'], + parserOptions: { + project: './packages/mcp/tsconfig.spec.json', + }, + }, ], settings: { react: { diff --git a/.github/workflows/backend-review.yml b/.github/workflows/backend-review.yml index 52560009a97..33316731a1e 100644 --- a/.github/workflows/backend-review.yml +++ b/.github/workflows/backend-review.yml @@ -33,8 +33,11 @@ jobs: - name: Install dependencies run: npm ci - - name: Install Data Provider + - name: Install Data Provider Package run: npm run build:data-provider + + - name: Install MCP Package + run: npm run build:mcp - name: Create empty auth.json file run: | diff --git a/.vscode/launch.json b/.vscode/launch.json index 16b4104980a..e393568b16f 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,7 +10,8 @@ "env": { "NODE_ENV": "production" }, - "console": "integratedTerminal" + "console": "integratedTerminal", + "envFile": "${workspaceFolder}/.env" } ] } diff --git a/Dockerfile b/Dockerfile index ba2414fdacd..41243119e1d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -# v0.7.5 +# v0.7.6 # Base node image FROM node:20-alpine AS node diff --git a/Dockerfile.multi b/Dockerfile.multi index 4d58de0c838..c5450026d3a 100644 --- a/Dockerfile.multi +++ b/Dockerfile.multi @@ -1,8 +1,8 @@ # Dockerfile.multi -# v0.7.5 +# v0.7.6 # Base for all builds -FROM node:20-alpine AS base +FROM node:20-alpine AS base-min WORKDIR /app RUN apk --no-cache add curl RUN npm config set fetch-retry-maxtimeout 600000 && \ @@ -10,8 +10,13 @@ RUN npm config set fetch-retry-maxtimeout 600000 && \ npm config set fetch-retry-mintimeout 15000 COPY package*.json ./ COPY packages/data-provider/package*.json ./packages/data-provider/ +COPY packages/mcp/package*.json ./packages/mcp/ COPY client/package*.json ./client/ COPY api/package*.json ./api/ + +# Install all dependencies for every build +FROM base-min AS base +WORKDIR /app RUN npm ci # Build data-provider @@ -19,7 +24,13 @@ FROM base AS data-provider-build WORKDIR /app/packages/data-provider COPY packages/data-provider ./ RUN npm run build -RUN npm prune --production + +# Build mcp package +FROM base AS mcp-build +WORKDIR /app/packages/mcp +COPY packages/mcp ./ +COPY --from=data-provider-build /app/packages/data-provider/dist /app/packages/data-provider/dist +RUN npm run build # Client build FROM base AS client-build @@ -28,17 +39,18 @@ COPY client ./ COPY --from=data-provider-build /app/packages/data-provider/dist /app/packages/data-provider/dist ENV NODE_OPTIONS="--max-old-space-size=2048" RUN npm run build -RUN npm prune --production # API setup (including client dist) -FROM base AS api-build +FROM base-min AS api-build WORKDIR /app +# Install only production deps +RUN npm ci --omit=dev COPY api ./api COPY config ./config COPY --from=data-provider-build /app/packages/data-provider/dist ./packages/data-provider/dist +COPY --from=mcp-build /app/packages/mcp/dist ./packages/mcp/dist COPY --from=client-build /app/client/dist ./client/dist WORKDIR /app/api -RUN npm prune --production EXPOSE 3080 ENV HOST=0.0.0.0 CMD ["node", "server/index.js"] diff --git a/README.md b/README.md index 0a1abe42df1..317a7a0669d 100644 --- a/README.md +++ b/README.md @@ -38,42 +38,73 @@
-# 📃 Features - -- 🖥️ UI matching ChatGPT, including Dark mode, Streaming, and latest updates -- 🤖 AI model selection: - - Anthropic (Claude), AWS Bedrock, OpenAI, Azure OpenAI, BingAI, ChatGPT, Google Vertex AI, Plugins, Assistants API (including Azure Assistants) -- ✅ Compatible across both **[Remote & Local AI services](https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints):** - - groq, Ollama, Cohere, Mistral AI, Apple MLX, koboldcpp, OpenRouter, together.ai, Perplexity, ShuttleAI, and more -- 🪄 Generative UI with **[Code Artifacts](https://youtu.be/GfTj7O4gmd0?si=WJbdnemZpJzBrJo3)** - - Create React, HTML code, and Mermaid diagrams right in chat -- 💾 Create, Save, & Share Custom Presets -- 🔀 Switch between AI Endpoints and Presets, mid-chat -- 🔄 Edit, Resubmit, and Continue Messages with Conversation branching -- 🌿 Fork Messages & Conversations for Advanced Context control -- 💬 Multimodal Chat: - - Upload and analyze images with Claude 3, GPT-4 (including `gpt-4o` and `gpt-4o-mini`), and Gemini Vision 📸 - - Chat with Files using Custom Endpoints, OpenAI, Azure, Anthropic, & Google. 🗃️ - - Advanced Agents with Files, Code Interpreter, Tools, and API Actions 🔦 - - Available through the [OpenAI Assistants API](https://platform.openai.com/docs/assistants/overview) 🌤️ - - Non-OpenAI Agents in Active Development 🚧 -- 🌎 Multilingual UI: - - English, 中文, Deutsch, Español, Français, Italiano, Polski, Português Brasileiro, +# ✨ Features + +- 🖥️ **UI & Experience** inspired by ChatGPT with enhanced design and features + +- 🤖 **AI Model Selection**: + - Anthropic (Claude), AWS Bedrock, OpenAI, Azure OpenAI, Google, Vertex AI, OpenAI Assistants API (incl. Azure) + - [Custom Endpoints](https://www.librechat.ai/docs/quick_start/custom_endpoints): Use any OpenAI-compatible API with LibreChat, no proxy required + - Compatible with [Local & Remote AI Providers](https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints): + - Ollama, groq, Cohere, Mistral AI, Apple MLX, koboldcpp, together.ai, + - OpenRouter, Perplexity, ShuttleAI, Deepseek, Qwen, and more + +- 🔧 **[Code Interpreter API](https://www.librechat.ai/docs/features/code_interpreter)**: + - Secure, Sandboxed Execution in Python, Node.js (JS/TS), Go, C/C++, Java, PHP, Rust, and Fortran + - Seamless File Handling: Upload, process, and download files directly + - No Privacy Concerns: Fully isolated and secure execution + +- 🔦 **Agents & Tools Integration**: + - **[LibreChat Agents](https://www.librechat.ai/docs/features/agents)**: + - No-Code Custom Assistants: Build specialized, AI-driven helpers without coding + - Flexible & Extensible: Attach tools like DALL-E-3, file search, code execution, and more + - Compatible with Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, and more + - [Model Context Protocol (MCP) Support](https://modelcontextprotocol.io/clients#librechat) for Tools + - Use LibreChat Agents and OpenAI Assistants with Files, Code Interpreter, Tools, and API Actions + +- 🪄 **Generative UI with Code Artifacts**: + - [Code Artifacts](https://youtu.be/GfTj7O4gmd0?si=WJbdnemZpJzBrJo3) allow creation of React, HTML, and Mermaid diagrams directly in chat + +- 💾 **Presets & Context Management**: + - Create, Save, & Share Custom Presets + - Switch between AI Endpoints and Presets mid-chat + - Edit, Resubmit, and Continue Messages with Conversation branching + - [Fork Messages & Conversations](https://www.librechat.ai/docs/features/fork) for Advanced Context control + +- 💬 **Multimodal & File Interactions**: + - Upload and analyze images with Claude 3, GPT-4o, o1, Llama-Vision, and Gemini 📸 + - Chat with Files using Custom Endpoints, OpenAI, Azure, Anthropic, AWS Bedrock, & Google 🗃️ + +- 🌎 **Multilingual UI**: + - English, 中文, Deutsch, Español, Français, Italiano, Polski, Português Brasileiro - Русский, 日本語, Svenska, 한국어, Tiếng Việt, 繁體中文, العربية, Türkçe, Nederlands, עברית -- 🎨 Customizable Dropdown & Interface: Adapts to both power users and newcomers -- 📧 Verify your email to ensure secure access -- 🗣️ Chat hands-free with Speech-to-Text and Text-to-Speech magic - - Automatically send and play Audio + +- 🎨 **Customizable Interface**: + - Customizable Dropdown & Interface that adapts to both power users and newcomers + +- 🗣️ **Speech & Audio**: + - Chat hands-free with Speech-to-Text and Text-to-Speech + - Automatically send and play Audio - Supports OpenAI, Azure OpenAI, and Elevenlabs -- 📥 Import Conversations from LibreChat, ChatGPT, Chatbot UI -- 📤 Export conversations as screenshots, markdown, text, json -- 🔍 Search all messages/conversations -- 🔌 Plugins, including web access, image generation with DALL-E-3 and more -- 👥 Multi-User, Secure Authentication with Moderation and Token spend tools -- ⚙️ Configure Proxy, Reverse Proxy, Docker, & many Deployment options: + +- 📥 **Import & Export Conversations**: + - Import Conversations from LibreChat, ChatGPT, Chatbot UI + - Export conversations as screenshots, markdown, text, json + +- 🔍 **Search & Discovery**: + - Search all messages/conversations + +- 👥 **Multi-User & Secure Access**: + - Multi-User, Secure Authentication with OAuth2, LDAP, & Email Login Support + - Built-in Moderation, and Token spend tools + +- ⚙️ **Configuration & Deployment**: + - Configure Proxy, Reverse Proxy, Docker, & many Deployment options - Use completely local or deploy on the cloud -- 📖 Completely Open-Source & Built in Public -- 🧑🤝🧑 Community-driven development, support, and feedback + +- 📖 **Open-Source & Community**: + - Completely Open-Source & Built in Public + - Community-driven development, support, and feedback [For a thorough review of our features, see our docs here](https://docs.librechat.ai/) 📚 @@ -83,7 +114,8 @@ LibreChat brings together the future of assistant AIs with the revolutionary tec With LibreChat, you no longer need to opt for ChatGPT Plus and can instead use free or pay-per-call APIs. We welcome contributions, cloning, and forking to enhance the capabilities of this advanced chatbot platform. -[![Watch the video](https://raw.githubusercontent.com/LibreChat-AI/librechat.ai/main/public/images/changelog/v0.7.5.png)](https://www.youtube.com/watch?v=IDukQ7a2f3U) +[![Watch the video](https://raw.githubusercontent.com/LibreChat-AI/librechat.ai/main/public/images/changelog/v0.7.6.gif)](https://www.youtube.com/watch?v=ilfwGQtJNlI) + Click on the thumbnail to open the video☝️ --- @@ -97,7 +129,7 @@ Click on the thumbnail to open the video☝️ **Other:** - **Website:** [librechat.ai](https://librechat.ai) - **Documentation:** [docs.librechat.ai](https://docs.librechat.ai) - - **Blog:** [blog.librechat.ai](https://docs.librechat.ai) + - **Blog:** [blog.librechat.ai](https://blog.librechat.ai) --- diff --git a/api/app/clients/AnthropicClient.js b/api/app/clients/AnthropicClient.js index 6e9d4accc20..8dc0e40d565 100644 --- a/api/app/clients/AnthropicClient.js +++ b/api/app/clients/AnthropicClient.js @@ -1,6 +1,5 @@ const Anthropic = require('@anthropic-ai/sdk'); const { HttpsProxyAgent } = require('https-proxy-agent'); -const { encoding_for_model: encodingForModel, get_encoding: getEncoding } = require('tiktoken'); const { Constants, EModelEndpoint, @@ -19,6 +18,7 @@ const { } = require('./prompts'); const { getModelMaxTokens, getModelMaxOutputTokens, matchModelName } = require('~/utils'); const { spendTokens, spendStructuredTokens } = require('~/models/spendTokens'); +const Tokenizer = require('~/server/services/Tokenizer'); const { sleep } = require('~/server/utils'); const BaseClient = require('./BaseClient'); const { logger } = require('~/config'); @@ -26,8 +26,6 @@ const { logger } = require('~/config'); const HUMAN_PROMPT = '\n\nHuman:'; const AI_PROMPT = '\n\nAssistant:'; -const tokenizersCache = {}; - /** Helper function to introduce a delay before retrying */ function delayBeforeRetry(attempts, baseDelay = 1000) { return new Promise((resolve) => setTimeout(resolve, baseDelay * attempts)); @@ -149,7 +147,6 @@ class AnthropicClient extends BaseClient { this.startToken = '||>'; this.endToken = ''; - this.gptEncoder = this.constructor.getTokenizer('cl100k_base'); return this; } @@ -849,22 +846,18 @@ class AnthropicClient extends BaseClient { logger.debug('AnthropicClient doesn\'t use getBuildMessagesOptions'); } - static getTokenizer(encoding, isModelName = false, extendSpecialTokens = {}) { - if (tokenizersCache[encoding]) { - return tokenizersCache[encoding]; - } - let tokenizer; - if (isModelName) { - tokenizer = encodingForModel(encoding, extendSpecialTokens); - } else { - tokenizer = getEncoding(encoding, extendSpecialTokens); - } - tokenizersCache[encoding] = tokenizer; - return tokenizer; + getEncoding() { + return 'cl100k_base'; } + /** + * Returns the token count of a given text. It also checks and resets the tokenizers if necessary. + * @param {string} text - The text to get the token count for. + * @returns {number} The token count of the given text. + */ getTokenCount(text) { - return this.gptEncoder.encode(text, 'all').length; + const encoding = this.getEncoding(); + return Tokenizer.getTokenCount(text, encoding); } /** diff --git a/api/app/clients/BaseClient.js b/api/app/clients/BaseClient.js index 33e3df3ac6e..5abdad686bd 100644 --- a/api/app/clients/BaseClient.js +++ b/api/app/clients/BaseClient.js @@ -50,6 +50,8 @@ class BaseClient { /** The key for the usage object's output tokens * @type {string} */ this.outputTokensKey = 'completion_tokens'; + /** @type {Set