mirror of
https://github.com/khoj-ai/khoj.git
synced 2024-12-18 18:47:11 +00:00
Merge branch 'master' of github.com:khoj-ai/khoj into features/allow-multi-outputs-in-chat
This commit is contained in:
commit
c5329d76ba
38 changed files with 437 additions and 180 deletions
|
@ -1,10 +1,11 @@
|
||||||
.git/
|
.*
|
||||||
.pytest_cache/
|
**/__pycache__/
|
||||||
.vscode/
|
*.egg-info/
|
||||||
.venv/
|
documentation/
|
||||||
docs/
|
|
||||||
tests/
|
tests/
|
||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
scripts/
|
scripts/
|
||||||
*.egg-info/
|
src/interface/
|
||||||
|
src/telemetry/
|
||||||
|
!src/interface/web
|
||||||
|
|
36
.github/workflows/dockerize.yml
vendored
36
.github/workflows/dockerize.yml
vendored
|
@ -38,13 +38,23 @@ env:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Publish Khoj Docker Images
|
name: Publish Khoj Docker Images
|
||||||
runs-on: ubuntu-linux-x64-high
|
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
image:
|
include:
|
||||||
- 'local'
|
- image: 'local'
|
||||||
- 'cloud'
|
platform: linux/amd64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
- image: 'local'
|
||||||
|
platform: linux/arm64
|
||||||
|
runner: ubuntu-linux-arm64
|
||||||
|
- image: 'cloud'
|
||||||
|
platform: linux/amd64
|
||||||
|
runner: ubuntu-latest
|
||||||
|
- image: 'cloud'
|
||||||
|
platform: linux/arm64
|
||||||
|
runner: ubuntu-linux-arm64
|
||||||
|
runs-on: ${{ matrix.runner }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Code
|
- name: Checkout Code
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
|
@ -73,12 +83,12 @@ jobs:
|
||||||
run: rm -rf /opt/hostedtoolcache
|
run: rm -rf /opt/hostedtoolcache
|
||||||
|
|
||||||
- name: 📦 Build and Push Docker Image
|
- name: 📦 Build and Push Docker Image
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v4
|
||||||
if: (matrix.image == 'local' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj == 'true' || (matrix.image == 'local' && github.event_name == 'push')
|
if: (matrix.image == 'local' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj == 'true' || (matrix.image == 'local' && github.event_name == 'push')
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: Dockerfile
|
file: Dockerfile
|
||||||
platforms: linux/amd64, linux/arm64
|
platforms: ${{ matrix.platform }}
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }}
|
ghcr.io/${{ github.repository }}:${{ env.DOCKER_IMAGE_TAG }}
|
||||||
|
@ -86,14 +96,19 @@ jobs:
|
||||||
build-args: |
|
build-args: |
|
||||||
VERSION=${{ steps.hatch.outputs.version }}
|
VERSION=${{ steps.hatch.outputs.version }}
|
||||||
PORT=42110
|
PORT=42110
|
||||||
|
cache-from: type=gha,scope=${{ matrix.image }}-${{ matrix.platform }}
|
||||||
|
cache-to: type=gha,mode=max,scope=${{ matrix.image }}-${{ matrix.platform}}
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.description=Khoj AI - Your second brain powered by LLMs and Neural Search
|
||||||
|
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||||
|
|
||||||
- name: 📦️⛅️ Build and Push Cloud Docker Image
|
- name: 📦️⛅️ Build and Push Cloud Docker Image
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v4
|
||||||
if: (matrix.image == 'cloud' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj-cloud == 'true' || (matrix.image == 'cloud' && github.event_name == 'push')
|
if: (matrix.image == 'cloud' && github.event_name == 'workflow_dispatch') && github.event.inputs.khoj-cloud == 'true' || (matrix.image == 'cloud' && github.event_name == 'push')
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: prod.Dockerfile
|
file: prod.Dockerfile
|
||||||
platforms: linux/amd64, linux/arm64
|
platforms: ${{ matrix.platform }}
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }}
|
ghcr.io/${{ github.repository }}-cloud:${{ env.DOCKER_IMAGE_TAG }}
|
||||||
|
@ -101,3 +116,8 @@ jobs:
|
||||||
build-args: |
|
build-args: |
|
||||||
VERSION=${{ steps.hatch.outputs.version }}
|
VERSION=${{ steps.hatch.outputs.version }}
|
||||||
PORT=42110
|
PORT=42110
|
||||||
|
cache-from: type=gha,scope=${{ matrix.image }}-${{ matrix.platform }}
|
||||||
|
cache-to: type=gha,mode=max,scope=${{ matrix.image }}-${{ matrix.platform}}
|
||||||
|
labels: |
|
||||||
|
org.opencontainers.image.description=Khoj AI Cloud - Your second brain powered by LLMs and Neural Search
|
||||||
|
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
|
||||||
|
|
7
.github/workflows/run_evals.yml
vendored
7
.github/workflows/run_evals.yml
vendored
|
@ -25,6 +25,8 @@ on:
|
||||||
options:
|
options:
|
||||||
- frames
|
- frames
|
||||||
- simpleqa
|
- simpleqa
|
||||||
|
- gpqa
|
||||||
|
- math500
|
||||||
sample_size:
|
sample_size:
|
||||||
description: 'Number of samples to evaluate'
|
description: 'Number of samples to evaluate'
|
||||||
required: false
|
required: false
|
||||||
|
@ -95,8 +97,9 @@ jobs:
|
||||||
KHOJ_URL: "http://localhost:42110"
|
KHOJ_URL: "http://localhost:42110"
|
||||||
KHOJ_LLM_SEED: "42"
|
KHOJ_LLM_SEED: "42"
|
||||||
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
|
||||||
SERPER_DEV_API_KEY: ${{ secrets.SERPER_DEV_API_KEY }}
|
SERPER_DEV_API_KEY: ${{ matrix.dataset != 'math500' && secrets.SERPER_DEV_API_KEY }}
|
||||||
OLOSTEP_API_KEY: ${{ secrets.OLOSTEP_API_KEY }}
|
OLOSTEP_API_KEY: ${{ matrix.dataset != 'math500' && secrets.OLOSTEP_API_KEY }}
|
||||||
|
HF_TOKEN: ${{ secrets.HF_TOKEN }}
|
||||||
KHOJ_ADMIN_EMAIL: khoj
|
KHOJ_ADMIN_EMAIL: khoj
|
||||||
KHOJ_ADMIN_PASSWORD: khoj
|
KHOJ_ADMIN_PASSWORD: khoj
|
||||||
POSTGRES_HOST: localhost
|
POSTGRES_HOST: localhost
|
||||||
|
|
11
.github/workflows/test.yml
vendored
11
.github/workflows/test.yml
vendored
|
@ -55,15 +55,13 @@ jobs:
|
||||||
with:
|
with:
|
||||||
python-version: ${{ matrix.python_version }}
|
python-version: ${{ matrix.python_version }}
|
||||||
|
|
||||||
- name: Install Git
|
|
||||||
run: |
|
|
||||||
apt update && apt install -y git
|
|
||||||
|
|
||||||
- name: ⏬️ Install Dependencies
|
- name: ⏬️ Install Dependencies
|
||||||
env:
|
env:
|
||||||
DEBIAN_FRONTEND: noninteractive
|
DEBIAN_FRONTEND: noninteractive
|
||||||
run: |
|
run: |
|
||||||
apt update && apt install -y libegl1 sqlite3 libsqlite3-dev libsqlite3-0 ffmpeg libsm6 libxext6
|
apt update && apt install -y git libegl1 sqlite3 libsqlite3-dev libsqlite3-0 ffmpeg libsm6 libxext6
|
||||||
|
# required by llama-cpp-python prebuilt wheels
|
||||||
|
apt install -y musl-dev && ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1
|
||||||
|
|
||||||
- name: ⬇️ Install Postgres
|
- name: ⬇️ Install Postgres
|
||||||
env:
|
env:
|
||||||
|
@ -78,6 +76,9 @@ jobs:
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
|
|
||||||
- name: ⬇️ Install Application
|
- name: ⬇️ Install Application
|
||||||
|
env:
|
||||||
|
PIP_EXTRA_INDEX_URL: "https://download.pytorch.org/whl/cpu https://abetlen.github.io/llama-cpp-python/whl/cpu"
|
||||||
|
CUDA_VISIBLE_DEVICES: ""
|
||||||
run: sed -i 's/dynamic = \["version"\]/version = "0.0.0"/' pyproject.toml && pip install --upgrade .[dev]
|
run: sed -i 's/dynamic = \["version"\]/version = "0.0.0"/' pyproject.toml && pip install --upgrade .[dev]
|
||||||
|
|
||||||
- name: 🧪 Test Application
|
- name: 🧪 Test Application
|
||||||
|
|
54
Dockerfile
54
Dockerfile
|
@ -1,5 +1,5 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
FROM ubuntu:jammy
|
FROM ubuntu:jammy AS base
|
||||||
LABEL homepage="https://khoj.dev"
|
LABEL homepage="https://khoj.dev"
|
||||||
LABEL repository="https://github.com/khoj-ai/khoj"
|
LABEL repository="https://github.com/khoj-ai/khoj"
|
||||||
LABEL org.opencontainers.image.source="https://github.com/khoj-ai/khoj"
|
LABEL org.opencontainers.image.source="https://github.com/khoj-ai/khoj"
|
||||||
|
@ -10,44 +10,54 @@ RUN apt update -y && apt -y install \
|
||||||
python3-pip \
|
python3-pip \
|
||||||
swig \
|
swig \
|
||||||
curl \
|
curl \
|
||||||
# Required by llama-cpp-python pre-built wheels. See #1628
|
|
||||||
musl-dev \
|
|
||||||
# Required by RapidOCR
|
# Required by RapidOCR
|
||||||
libgl1 \
|
libgl1 \
|
||||||
libglx-mesa0 \
|
libglx-mesa0 \
|
||||||
libglib2.0-0 && \
|
libglib2.0-0 \
|
||||||
# Required by Next.js Web app
|
|
||||||
curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
|
|
||||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
|
||||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
|
||||||
apt update -y && apt -y --no-install-recommends install nodejs yarn && \
|
|
||||||
apt clean && rm -rf /var/lib/apt/lists/* && \
|
|
||||||
# Required by llama-cpp-python pre-built wheels. See #1628
|
# Required by llama-cpp-python pre-built wheels. See #1628
|
||||||
ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1
|
musl-dev && \
|
||||||
|
ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1 && \
|
||||||
|
# Clean up
|
||||||
|
apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# Install Application
|
# Build Server
|
||||||
|
FROM base AS server-deps
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY pyproject.toml .
|
COPY pyproject.toml .
|
||||||
COPY README.md .
|
COPY README.md .
|
||||||
ARG VERSION=0.0.0
|
ARG VERSION=0.0.0
|
||||||
ENV PIP_EXTRA_INDEX_URL=https://abetlen.github.io/llama-cpp-python/whl/cpu
|
# use the pre-built llama-cpp-python, torch cpu wheel
|
||||||
|
ENV PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu https://abetlen.github.io/llama-cpp-python/whl/cpu"
|
||||||
|
# avoid downloading unused cuda specific python packages
|
||||||
|
ENV CUDA_VISIBLE_DEVICES=""
|
||||||
RUN sed -i "s/dynamic = \\[\"version\"\\]/version = \"$VERSION\"/" pyproject.toml && \
|
RUN sed -i "s/dynamic = \\[\"version\"\\]/version = \"$VERSION\"/" pyproject.toml && \
|
||||||
pip install --no-cache-dir .
|
pip install --no-cache-dir .
|
||||||
|
|
||||||
# Copy Source Code
|
# Build Web App
|
||||||
COPY . .
|
FROM node:20-alpine AS web-app
|
||||||
|
# Set build optimization env vars
|
||||||
# Set the PYTHONPATH environment variable in order for it to find the Django app.
|
ENV NODE_ENV=production
|
||||||
ENV PYTHONPATH=/app/src:$PYTHONPATH
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
# Go to the directory src/interface/web and export the built Next.js assets
|
|
||||||
WORKDIR /app/src/interface/web
|
WORKDIR /app/src/interface/web
|
||||||
RUN bash -c "yarn install --frozen-lockfile && yarn ciexport && yarn cache clean"
|
# Install dependencies first (cache layer)
|
||||||
|
COPY src/interface/web/package.json src/interface/web/yarn.lock ./
|
||||||
|
RUN yarn install --frozen-lockfile
|
||||||
|
# Copy source and build
|
||||||
|
COPY src/interface/web/. ./
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
# Merge the Server and Web App into a Single Image
|
||||||
|
FROM base
|
||||||
|
ENV PYTHONPATH=/app/src
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
COPY --from=server-deps /usr/local/lib/python3.10/dist-packages /usr/local/lib/python3.10/dist-packages
|
||||||
|
COPY --from=web-app /app/src/interface/web/out ./src/khoj/interface/built
|
||||||
|
COPY . .
|
||||||
|
RUN cd src && python3 khoj/manage.py collectstatic --noinput
|
||||||
|
|
||||||
# Run the Application
|
# Run the Application
|
||||||
# There are more arguments required for the application to run,
|
# There are more arguments required for the application to run,
|
||||||
# but these should be passed in through the docker-compose.yml file.
|
# but those should be passed in through the docker-compose.yml file.
|
||||||
ARG PORT
|
ARG PORT
|
||||||
EXPOSE ${PORT}
|
EXPOSE ${PORT}
|
||||||
ENTRYPOINT ["python3", "src/khoj/main.py"]
|
ENTRYPOINT ["python3", "src/khoj/main.py"]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "khoj",
|
"id": "khoj",
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.30.7",
|
"version": "1.30.10",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "Your Second Brain",
|
"description": "Your Second Brain",
|
||||||
"author": "Khoj Inc.",
|
"author": "Khoj Inc.",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# syntax=docker/dockerfile:1
|
# syntax=docker/dockerfile:1
|
||||||
FROM ubuntu:jammy
|
FROM ubuntu:jammy AS base
|
||||||
LABEL homepage="https://khoj.dev"
|
LABEL homepage="https://khoj.dev"
|
||||||
LABEL repository="https://github.com/khoj-ai/khoj"
|
LABEL repository="https://github.com/khoj-ai/khoj"
|
||||||
LABEL org.opencontainers.image.source="https://github.com/khoj-ai/khoj"
|
LABEL org.opencontainers.image.source="https://github.com/khoj-ai/khoj"
|
||||||
|
@ -16,38 +16,49 @@ RUN apt update -y && apt -y install \
|
||||||
curl \
|
curl \
|
||||||
# Required by llama-cpp-python pre-built wheels. See #1628
|
# Required by llama-cpp-python pre-built wheels. See #1628
|
||||||
musl-dev && \
|
musl-dev && \
|
||||||
# Required by Next.js Web app
|
ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1 && \
|
||||||
curl -sL https://deb.nodesource.com/setup_20.x | bash - && \
|
# Clean up
|
||||||
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
|
apt clean && rm -rf /var/lib/apt/lists/*
|
||||||
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
|
|
||||||
apt update -y && apt -y --no-install-recommends install nodejs yarn && \
|
|
||||||
apt clean && rm -rf /var/lib/apt/lists/* && \
|
|
||||||
# Required by llama-cpp-python pre-built wheels. See #1628
|
|
||||||
ln -s /usr/lib/x86_64-linux-musl/libc.so /lib/libc.musl-x86_64.so.1
|
|
||||||
|
|
||||||
# Install Application
|
# Build Server
|
||||||
|
FROM base AS server-deps
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY pyproject.toml .
|
COPY pyproject.toml .
|
||||||
COPY README.md .
|
COPY README.md .
|
||||||
ARG VERSION=0.0.0
|
ARG VERSION=0.0.0
|
||||||
ENV PIP_EXTRA_INDEX_URL=https://abetlen.github.io/llama-cpp-python/whl/cpu
|
# use the pre-built llama-cpp-python, torch cpu wheel
|
||||||
|
ENV PIP_EXTRA_INDEX_URL="https://download.pytorch.org/whl/cpu https://abetlen.github.io/llama-cpp-python/whl/cpu"
|
||||||
|
# avoid downloading unused cuda specific python packages
|
||||||
|
ENV CUDA_VISIBLE_DEVICES=""
|
||||||
RUN sed -i "s/dynamic = \\[\"version\"\\]/version = \"$VERSION\"/" pyproject.toml && \
|
RUN sed -i "s/dynamic = \\[\"version\"\\]/version = \"$VERSION\"/" pyproject.toml && \
|
||||||
pip install --no-cache-dir -e .[prod]
|
pip install --no-cache-dir -e .[prod]
|
||||||
|
|
||||||
# Copy Source Code
|
# Build Web App
|
||||||
COPY . .
|
FROM node:20-alpine AS web-app
|
||||||
|
# Set build optimization env vars
|
||||||
# Set the PYTHONPATH environment variable in order for it to find the Django app.
|
ENV NODE_ENV=production
|
||||||
ENV PYTHONPATH=/app/src:$PYTHONPATH
|
ENV NEXT_TELEMETRY_DISABLED=1
|
||||||
|
|
||||||
# Go to the directory src/interface/web and export the built Next.js assets
|
|
||||||
WORKDIR /app/src/interface/web
|
WORKDIR /app/src/interface/web
|
||||||
RUN bash -c "yarn install --frozen-lockfile && yarn ciexport && yarn cache clean"
|
# Install dependencies first (cache layer)
|
||||||
|
COPY src/interface/web/package.json src/interface/web/yarn.lock ./
|
||||||
|
RUN yarn install --frozen-lockfile
|
||||||
|
# Copy source and build
|
||||||
|
COPY src/interface/web/. ./
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
# Merge the Server and Web App into a Single Image
|
||||||
|
FROM base
|
||||||
|
ENV PYTHONPATH=/app/src:$PYTHONPATH
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
COPY --from=server-deps /usr/local/lib/python3.10/dist-packages /usr/local/lib/python3.10/dist-packages
|
||||||
|
COPY --from=server-deps /usr/local/bin /usr/local/bin
|
||||||
|
COPY --from=web-app /app/src/interface/web/out ./src/khoj/interface/built
|
||||||
|
COPY . .
|
||||||
|
RUN cd src && python3 khoj/manage.py collectstatic --noinput
|
||||||
|
|
||||||
# Run the Application
|
# Run the Application
|
||||||
# There are more arguments required for the application to run,
|
# There are more arguments required for the application to run,
|
||||||
# but these should be passed in through the docker-compose.yml file.
|
# but those should be passed in through the docker-compose.yml file.
|
||||||
ARG PORT
|
ARG PORT
|
||||||
EXPOSE ${PORT}
|
EXPOSE ${PORT}
|
||||||
ENTRYPOINT ["gunicorn", "-c", "gunicorn-config.py", "src.khoj.main:app"]
|
ENTRYPOINT ["gunicorn", "-c", "gunicorn-config.py", "src.khoj.main:app"]
|
||||||
|
|
|
@ -88,6 +88,7 @@ dependencies = [
|
||||||
"anthropic == 0.26.1",
|
"anthropic == 0.26.1",
|
||||||
"docx2txt == 0.8",
|
"docx2txt == 0.8",
|
||||||
"google-generativeai == 0.8.3",
|
"google-generativeai == 0.8.3",
|
||||||
|
"pyjson5 == 1.6.7",
|
||||||
]
|
]
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.30.7",
|
"version": "1.30.10",
|
||||||
"description": "Your Second Brain",
|
"description": "Your Second Brain",
|
||||||
"author": "Khoj Inc. <team@khoj.dev>",
|
"author": "Khoj Inc. <team@khoj.dev>",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
"start": "yarn electron ."
|
"start": "yarn electron ."
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@todesktop/runtime": "^1.6.4",
|
"@todesktop/runtime": "^2.0.0",
|
||||||
"axios": "^1.7.4",
|
"axios": "^1.7.4",
|
||||||
"cron": "^2.4.3",
|
"cron": "^2.4.3",
|
||||||
"electron-store": "^8.1.0"
|
"electron-store": "^8.1.0"
|
||||||
|
|
|
@ -50,17 +50,17 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect "^2.0.0"
|
defer-to-connect "^2.0.0"
|
||||||
|
|
||||||
"@todesktop/runtime@^1.6.4":
|
"@todesktop/runtime@^2.0.0":
|
||||||
version "1.6.4"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@todesktop/runtime/-/runtime-1.6.4.tgz#a9d62a021cf2647c51371c892bfb1d4c5a29ed7e"
|
resolved "https://registry.yarnpkg.com/@todesktop/runtime/-/runtime-2.0.0.tgz#dfd409186ae664f5e28186a03b99e620ec7b7f82"
|
||||||
integrity sha512-n6dOxhrKKsXMM+i2u9iRvoJSR2KCWw0orYK+FT9RbWNPykhuFIYd0yy8dYgYy/OuClKGyGl4SJFi2757FLhWDA==
|
integrity sha512-0a2tmWpIc/HJE/873xRMZKQNggfrYhoKYIchfN+k8RqKdzTPwTWa5ztur7GdCHLHBUaiMBPNRzF3h4kwHd1NCw==
|
||||||
dependencies:
|
dependencies:
|
||||||
del "^6.0.0"
|
del "^6.1.1"
|
||||||
electron-updater "^4.6.1"
|
electron-updater "^6.3.9"
|
||||||
eventemitter2 "^6.4.5"
|
eventemitter2 "^6.4.9"
|
||||||
execa "^5.0.0"
|
execa "^5.0.0"
|
||||||
lodash.once "^4.1.1"
|
lodash.once "^4.1.1"
|
||||||
semver "^7.3.2"
|
semver "^7.6.3"
|
||||||
|
|
||||||
"@types/cacheable-request@^6.0.1":
|
"@types/cacheable-request@^6.0.1":
|
||||||
version "6.0.3"
|
version "6.0.3"
|
||||||
|
@ -90,16 +90,16 @@
|
||||||
integrity sha512-jYvz8UMLDgy3a5SkGJne8H7VA7zPV2Lwohjx0V8V31+SqAjNmurWMkk9cQhfvlcnXWudBpK9xPM1n4rljOcHYQ==
|
integrity sha512-jYvz8UMLDgy3a5SkGJne8H7VA7zPV2Lwohjx0V8V31+SqAjNmurWMkk9cQhfvlcnXWudBpK9xPM1n4rljOcHYQ==
|
||||||
|
|
||||||
"@types/node@*":
|
"@types/node@*":
|
||||||
version "22.9.1"
|
version "22.10.1"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.1.tgz#bdf91c36e0e7ecfb7257b2d75bf1b206b308ca71"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.1.tgz#41ffeee127b8975a05f8c4f83fb89bcb2987d766"
|
||||||
integrity sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==
|
integrity sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~6.19.8"
|
undici-types "~6.20.0"
|
||||||
|
|
||||||
"@types/node@^18.11.18":
|
"@types/node@^18.11.18":
|
||||||
version "18.19.64"
|
version "18.19.67"
|
||||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.64.tgz#122897fb79f2a9ec9c979bded01c11461b2b1478"
|
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.67.tgz#77c4b01641a1e3e1509aff7e10d39e4afd5ae06d"
|
||||||
integrity sha512-955mDqvO2vFf/oL7V3WiUtiz+BugyX8uVbaT2H8oj3+8dRyH2FLiNdowe7eNqRM7IOIZvzDH76EoAT+gwm6aIQ==
|
integrity sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types "~5.26.4"
|
undici-types "~5.26.4"
|
||||||
|
|
||||||
|
@ -110,11 +110,6 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/semver@^7.3.6":
|
|
||||||
version "7.5.8"
|
|
||||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e"
|
|
||||||
integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==
|
|
||||||
|
|
||||||
"@types/yauzl@^2.9.1":
|
"@types/yauzl@^2.9.1":
|
||||||
version "2.10.3"
|
version "2.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999"
|
resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999"
|
||||||
|
@ -168,9 +163,9 @@ atomically@^1.7.0:
|
||||||
integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==
|
integrity sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==
|
||||||
|
|
||||||
axios@^1.7.4:
|
axios@^1.7.4:
|
||||||
version "1.7.7"
|
version "1.7.8"
|
||||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f"
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.8.tgz#1997b1496b394c21953e68c14aaa51b7b5de3d6e"
|
||||||
integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==
|
integrity sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.15.6"
|
follow-redirects "^1.15.6"
|
||||||
form-data "^4.0.0"
|
form-data "^4.0.0"
|
||||||
|
@ -206,12 +201,12 @@ buffer-crc32@~0.2.3:
|
||||||
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
|
||||||
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
|
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
|
||||||
|
|
||||||
builder-util-runtime@8.9.2:
|
builder-util-runtime@9.2.10:
|
||||||
version "8.9.2"
|
version "9.2.10"
|
||||||
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz#a9669ae5b5dcabfe411ded26678e7ae997246c28"
|
resolved "https://registry.yarnpkg.com/builder-util-runtime/-/builder-util-runtime-9.2.10.tgz#a0f7d9e214158402e78b74a745c8d9f870c604bc"
|
||||||
integrity sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==
|
integrity sha512-6p/gfG1RJSQeIbz8TK5aPNkoztgY1q5TgmGFMAXcY8itsGW6Y2ld1ALsZ5UJn8rog7hKF3zHx5iQbNQ8uLcRlw==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.3.2"
|
debug "^4.3.4"
|
||||||
sax "^1.2.4"
|
sax "^1.2.4"
|
||||||
|
|
||||||
cacheable-lookup@^5.0.3:
|
cacheable-lookup@^5.0.3:
|
||||||
|
@ -296,7 +291,7 @@ debounce-fn@^4.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
mimic-fn "^3.0.0"
|
mimic-fn "^3.0.0"
|
||||||
|
|
||||||
debug@^4.1.0, debug@^4.1.1, debug@^4.3.2:
|
debug@^4.1.0, debug@^4.1.1, debug@^4.3.4:
|
||||||
version "4.3.7"
|
version "4.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
|
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
|
||||||
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
|
integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
|
||||||
|
@ -333,7 +328,7 @@ define-properties@^1.2.1:
|
||||||
has-property-descriptors "^1.0.0"
|
has-property-descriptors "^1.0.0"
|
||||||
object-keys "^1.1.1"
|
object-keys "^1.1.1"
|
||||||
|
|
||||||
del@^6.0.0:
|
del@^6.1.1:
|
||||||
version "6.1.1"
|
version "6.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a"
|
resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a"
|
||||||
integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==
|
integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==
|
||||||
|
@ -379,19 +374,19 @@ electron-store@^8.1.0:
|
||||||
conf "^10.2.0"
|
conf "^10.2.0"
|
||||||
type-fest "^2.17.0"
|
type-fest "^2.17.0"
|
||||||
|
|
||||||
electron-updater@^4.6.1:
|
electron-updater@^6.3.9:
|
||||||
version "4.6.5"
|
version "6.3.9"
|
||||||
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-4.6.5.tgz#e9a75458bbfd6bb41a58a829839e150ad2eb2d3d"
|
resolved "https://registry.yarnpkg.com/electron-updater/-/electron-updater-6.3.9.tgz#e1e7f155624c58e6f3760f376c3a584028165ec4"
|
||||||
integrity sha512-kdTly8O9mSZfm9fslc1mnCY+mYOeaYRy7ERa2Fed240u01BKll3aiupzkd07qKw69KvhBSzuHroIW3mF0D8DWA==
|
integrity sha512-2PJNONi+iBidkoC5D1nzT9XqsE8Q1X28Fn6xRQhO3YX8qRRyJ3mkV4F1aQsuRnYPqq6Hw+E51y27W75WgDoofw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/semver" "^7.3.6"
|
builder-util-runtime "9.2.10"
|
||||||
builder-util-runtime "8.9.2"
|
fs-extra "^10.1.0"
|
||||||
fs-extra "^10.0.0"
|
|
||||||
js-yaml "^4.1.0"
|
js-yaml "^4.1.0"
|
||||||
lazy-val "^1.0.5"
|
lazy-val "^1.0.5"
|
||||||
lodash.escaperegexp "^4.1.2"
|
lodash.escaperegexp "^4.1.2"
|
||||||
lodash.isequal "^4.5.0"
|
lodash.isequal "^4.5.0"
|
||||||
semver "^7.3.5"
|
semver "^7.6.3"
|
||||||
|
tiny-typed-emitter "^2.1.0"
|
||||||
|
|
||||||
electron@28.2.1:
|
electron@28.2.1:
|
||||||
version "28.2.1"
|
version "28.2.1"
|
||||||
|
@ -436,7 +431,7 @@ escape-string-regexp@^4.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
|
||||||
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
|
||||||
|
|
||||||
eventemitter2@^6.4.5:
|
eventemitter2@^6.4.9:
|
||||||
version "6.4.9"
|
version "6.4.9"
|
||||||
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.9.tgz#41f2750781b4230ed58827bc119d293471ecb125"
|
resolved "https://registry.yarnpkg.com/eventemitter2/-/eventemitter2-6.4.9.tgz#41f2750781b4230ed58827bc119d293471ecb125"
|
||||||
integrity sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==
|
integrity sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==
|
||||||
|
@ -530,7 +525,7 @@ form-data@^4.0.0:
|
||||||
combined-stream "^1.0.8"
|
combined-stream "^1.0.8"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
fs-extra@^10.0.0:
|
fs-extra@^10.1.0:
|
||||||
version "10.1.0"
|
version "10.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
||||||
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
|
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
|
||||||
|
@ -1115,7 +1110,7 @@ semver@^6.2.0:
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
|
||||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.3.2, semver@^7.3.5:
|
semver@^7.3.2, semver@^7.3.5, semver@^7.6.3:
|
||||||
version "7.6.3"
|
version "7.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
|
||||||
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
|
||||||
|
@ -1166,6 +1161,11 @@ sumchecker@^3.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "^4.1.0"
|
debug "^4.1.0"
|
||||||
|
|
||||||
|
tiny-typed-emitter@^2.1.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz#b3b027fdd389ff81a152c8e847ee2f5be9fad7b5"
|
||||||
|
integrity sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==
|
||||||
|
|
||||||
to-regex-range@^5.0.1:
|
to-regex-range@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||||
|
@ -1188,10 +1188,10 @@ undici-types@~5.26.4:
|
||||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
|
||||||
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
|
||||||
|
|
||||||
undici-types@~6.19.8:
|
undici-types@~6.20.0:
|
||||||
version "6.19.8"
|
version "6.20.0"
|
||||||
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02"
|
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
|
||||||
integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==
|
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
|
||||||
|
|
||||||
universalify@^0.1.0:
|
universalify@^0.1.0:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
;; Saba Imran <saba@khoj.dev>
|
;; Saba Imran <saba@khoj.dev>
|
||||||
;; Description: Your Second Brain
|
;; Description: Your Second Brain
|
||||||
;; Keywords: search, chat, ai, org-mode, outlines, markdown, pdf, image
|
;; Keywords: search, chat, ai, org-mode, outlines, markdown, pdf, image
|
||||||
;; Version: 1.30.7
|
;; Version: 1.30.10
|
||||||
;; Package-Requires: ((emacs "27.1") (transient "0.3.0") (dash "2.19.1"))
|
;; Package-Requires: ((emacs "27.1") (transient "0.3.0") (dash "2.19.1"))
|
||||||
;; URL: https://github.com/khoj-ai/khoj/tree/master/src/interface/emacs
|
;; URL: https://github.com/khoj-ai/khoj/tree/master/src/interface/emacs
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "khoj",
|
"id": "khoj",
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.30.7",
|
"version": "1.30.10",
|
||||||
"minAppVersion": "0.15.0",
|
"minAppVersion": "0.15.0",
|
||||||
"description": "Your Second Brain",
|
"description": "Your Second Brain",
|
||||||
"author": "Khoj Inc.",
|
"author": "Khoj Inc.",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Khoj",
|
"name": "Khoj",
|
||||||
"version": "1.30.7",
|
"version": "1.30.10",
|
||||||
"description": "Your Second Brain",
|
"description": "Your Second Brain",
|
||||||
"author": "Debanjum Singh Solanky, Saba Imran <team@khoj.dev>",
|
"author": "Debanjum Singh Solanky, Saba Imran <team@khoj.dev>",
|
||||||
"license": "GPL-3.0-or-later",
|
"license": "GPL-3.0-or-later",
|
||||||
|
|
|
@ -98,5 +98,8 @@
|
||||||
"1.30.4": "0.15.0",
|
"1.30.4": "0.15.0",
|
||||||
"1.30.5": "0.15.0",
|
"1.30.5": "0.15.0",
|
||||||
"1.30.6": "0.15.0",
|
"1.30.6": "0.15.0",
|
||||||
"1.30.7": "0.15.0"
|
"1.30.7": "0.15.0",
|
||||||
|
"1.30.8": "0.15.0",
|
||||||
|
"1.30.9": "0.15.0",
|
||||||
|
"1.30.10": "0.15.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Noto_Sans } from "next/font/google";
|
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||||
import "../globals.css";
|
import "../globals.css";
|
||||||
|
|
||||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Khoj AI - Agents",
|
title: "Khoj AI - Agents",
|
||||||
description: "Find a specialized agent that can help you address more specific needs.",
|
description: "Find a specialized agent that can help you address more specific needs.",
|
||||||
|
@ -33,7 +31,7 @@ export default function RootLayout({
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||||
<meta
|
<meta
|
||||||
httpEquiv="Content-Security-Policy"
|
httpEquiv="Content-Security-Policy"
|
||||||
content="default-src 'self' https://assets.khoj.dev;
|
content="default-src 'self' https://assets.khoj.dev;
|
||||||
|
@ -46,7 +44,7 @@ export default function RootLayout({
|
||||||
child-src 'none';
|
child-src 'none';
|
||||||
object-src 'none';"
|
object-src 'none';"
|
||||||
></meta>
|
></meta>
|
||||||
<body className={inter.className}>{children}</body>
|
<body>{children}</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Noto_Sans } from "next/font/google";
|
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||||
import "../globals.css";
|
import "../globals.css";
|
||||||
|
|
||||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Khoj AI - Chat",
|
title: "Khoj AI - Chat",
|
||||||
description:
|
description:
|
||||||
|
@ -34,7 +32,7 @@ export default function RootLayout({
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||||
<meta
|
<meta
|
||||||
httpEquiv="Content-Security-Policy"
|
httpEquiv="Content-Security-Policy"
|
||||||
content="default-src 'self' https://assets.khoj.dev;
|
content="default-src 'self' https://assets.khoj.dev;
|
||||||
|
@ -47,7 +45,7 @@ export default function RootLayout({
|
||||||
child-src 'none';
|
child-src 'none';
|
||||||
object-src 'none';"
|
object-src 'none';"
|
||||||
></meta>
|
></meta>
|
||||||
<body className={inter.className}>
|
<body>
|
||||||
{children}
|
{children}
|
||||||
<script
|
<script
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
|
|
13
src/interface/web/app/fonts.ts
Normal file
13
src/interface/web/app/fonts.ts
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import { Noto_Sans, Noto_Sans_Arabic } from "next/font/google";
|
||||||
|
|
||||||
|
export const noto_sans = Noto_Sans({
|
||||||
|
subsets: ["latin", "latin-ext", "cyrillic", "cyrillic-ext", "devanagari", "vietnamese"],
|
||||||
|
display: "swap",
|
||||||
|
variable: "--font-noto-sans",
|
||||||
|
});
|
||||||
|
|
||||||
|
export const noto_sans_arabic = Noto_Sans_Arabic({
|
||||||
|
subsets: ["arabic"],
|
||||||
|
display: "swap",
|
||||||
|
variable: "--font-noto-sans-arabic",
|
||||||
|
});
|
|
@ -1,7 +1,6 @@
|
||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:wght@100..900&family=Noto+Sans:ital,wght@0,100..900;1,100..900&display=swap");
|
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
|
@ -25,7 +24,7 @@
|
||||||
--input: 220 13% 91%;
|
--input: 220 13% 91%;
|
||||||
--ring: 24.6 95% 53.1%;
|
--ring: 24.6 95% 53.1%;
|
||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
--font-family: "Noto Sans", "Noto Sans Arabic", sans-serif !important;
|
--font-family: var(--font-noto-sans), var(--font-noto-sans-arabic), sans-serif !important;
|
||||||
|
|
||||||
/* Khoj Custom Colors */
|
/* Khoj Custom Colors */
|
||||||
--frosted-background-color: 20 13% 95%;
|
--frosted-background-color: 20 13% 95%;
|
||||||
|
@ -188,7 +187,7 @@
|
||||||
--border: 0 0% 9%;
|
--border: 0 0% 9%;
|
||||||
--input: 0 0% 9%;
|
--input: 0 0% 9%;
|
||||||
--ring: 20.5 90.2% 48.2%;
|
--ring: 20.5 90.2% 48.2%;
|
||||||
--font-family: "Noto Sans", "Noto Sans Arabic", sans-serif !important;
|
--font-family: var(--font-noto-sans), var(--font-noto-sans-arabic), sans-serif !important;
|
||||||
|
|
||||||
/* Imported from highlight.js */
|
/* Imported from highlight.js */
|
||||||
pre code.hljs {
|
pre code.hljs {
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Noto_Sans } from "next/font/google";
|
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Khoj AI - Home",
|
title: "Khoj AI - Home",
|
||||||
description: "Your Second Brain.",
|
description: "Your Second Brain.",
|
||||||
|
@ -39,7 +37,7 @@ export default function RootLayout({
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||||
<meta
|
<meta
|
||||||
httpEquiv="Content-Security-Policy"
|
httpEquiv="Content-Security-Policy"
|
||||||
content="default-src 'self' https://assets.khoj.dev;
|
content="default-src 'self' https://assets.khoj.dev;
|
||||||
|
@ -52,7 +50,7 @@ export default function RootLayout({
|
||||||
child-src 'none';
|
child-src 'none';
|
||||||
object-src 'none';"
|
object-src 'none';"
|
||||||
></meta>
|
></meta>
|
||||||
<body className={inter.className}>{children}</body>
|
<body>{children}</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Noto_Sans } from "next/font/google";
|
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||||
import "../globals.css";
|
import "../globals.css";
|
||||||
import { Toaster } from "@/components/ui/toaster";
|
import { Toaster } from "@/components/ui/toaster";
|
||||||
|
|
||||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Khoj AI - Settings",
|
title: "Khoj AI - Settings",
|
||||||
description: "Configure Khoj to get personalized, deeper assistance.",
|
description: "Configure Khoj to get personalized, deeper assistance.",
|
||||||
|
@ -34,7 +32,7 @@ export default function RootLayout({
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||||
<meta
|
<meta
|
||||||
httpEquiv="Content-Security-Policy"
|
httpEquiv="Content-Security-Policy"
|
||||||
content="default-src 'self' https://assets.khoj.dev;
|
content="default-src 'self' https://assets.khoj.dev;
|
||||||
|
@ -46,7 +44,7 @@ export default function RootLayout({
|
||||||
child-src 'none';
|
child-src 'none';
|
||||||
object-src 'none';"
|
object-src 'none';"
|
||||||
></meta>
|
></meta>
|
||||||
<body className={inter.className}>
|
<body>
|
||||||
{children}
|
{children}
|
||||||
<Toaster />
|
<Toaster />
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { Noto_Sans } from "next/font/google";
|
import { noto_sans, noto_sans_arabic } from "@/app/fonts";
|
||||||
import "../../globals.css";
|
import "../../globals.css";
|
||||||
|
|
||||||
const inter = Noto_Sans({ subsets: ["latin"] });
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Khoj AI - Chat",
|
title: "Khoj AI - Chat",
|
||||||
description: "Use this page to view a chat with Khoj AI.",
|
description: "Use this page to view a chat with Khoj AI.",
|
||||||
|
@ -15,7 +13,7 @@ export default function RootLayout({
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en" className={`${noto_sans.variable} ${noto_sans_arabic.variable}`}>
|
||||||
<meta
|
<meta
|
||||||
httpEquiv="Content-Security-Policy"
|
httpEquiv="Content-Security-Policy"
|
||||||
content="default-src 'self' https://assets.khoj.dev;
|
content="default-src 'self' https://assets.khoj.dev;
|
||||||
|
@ -27,7 +25,7 @@ export default function RootLayout({
|
||||||
child-src 'none';
|
child-src 'none';
|
||||||
object-src 'none';"
|
object-src 'none';"
|
||||||
></meta>
|
></meta>
|
||||||
<body className={inter.className}>
|
<body>
|
||||||
{children}
|
{children}
|
||||||
<script
|
<script
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "khoj-ai",
|
"name": "khoj-ai",
|
||||||
"version": "1.30.7",
|
"version": "1.30.10",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
@ -62,6 +62,9 @@
|
||||||
"react-hook-form": "^7.52.1",
|
"react-hook-form": "^7.52.1",
|
||||||
"shadcn-ui": "^0.8.0",
|
"shadcn-ui": "^0.8.0",
|
||||||
"swr": "^2.2.5",
|
"swr": "^2.2.5",
|
||||||
|
"tailwind-merge": "^2.3.0",
|
||||||
|
"tailwindcss": "^3.4.6",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"typescript": "^5",
|
"typescript": "^5",
|
||||||
"vaul": "^0.9.1",
|
"vaul": "^0.9.1",
|
||||||
"zod": "^3.23.8"
|
"zod": "^3.23.8"
|
||||||
|
@ -82,9 +85,6 @@
|
||||||
"lint-staged": "^15.2.7",
|
"lint-staged": "^15.2.7",
|
||||||
"nodemon": "^3.1.3",
|
"nodemon": "^3.1.3",
|
||||||
"prettier": "3.3.3",
|
"prettier": "3.3.3",
|
||||||
"tailwind-merge": "^2.3.0",
|
|
||||||
"tailwindcss": "^3.4.6",
|
|
||||||
"tailwindcss-animate": "^1.0.7",
|
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
|
|
|
@ -55,6 +55,9 @@ const config = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
extend: {
|
extend: {
|
||||||
|
fontFamily: {
|
||||||
|
sans: ["var(--font-noto-sans)", "var(--font-noto-sans-arabic)"],
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
border: "hsl(var(--border))",
|
border: "hsl(var(--border))",
|
||||||
input: "hsl(var(--input))",
|
input: "hsl(var(--input))",
|
||||||
|
|
11
src/khoj/interface/web/.well-known/assetlinks.json
Normal file
11
src/khoj/interface/web/.well-known/assetlinks.json
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[{
|
||||||
|
"relation": ["delegate_permission/common.handle_all_urls"],
|
||||||
|
"target": {
|
||||||
|
"namespace": "android_app",
|
||||||
|
"package_name": "dev.khoj.app",
|
||||||
|
"sha256_cert_fingerprints": [
|
||||||
|
"CC:98:4A:0A:F1:CC:84:26:AC:02:86:49:AA:69:64:B9:5E:63:A3:EF:18:56:EA:CA:13:C1:3A:15:CA:49:77:46",
|
||||||
|
"D4:5A:6F:6C:18:28:D2:1C:78:27:92:C6:AC:DB:4C:12:C4:52:A1:88:9B:A1:F5:67:D1:22:FE:A0:0F:B1:AE:92"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}]
|
|
@ -1,9 +1,8 @@
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
import pyjson5
|
||||||
from langchain.schema import ChatMessage
|
from langchain.schema import ChatMessage
|
||||||
|
|
||||||
from khoj.database.models import Agent, ChatModelOptions, KhojUser
|
from khoj.database.models import Agent, ChatModelOptions, KhojUser
|
||||||
|
@ -110,7 +109,7 @@ def extract_questions_anthropic(
|
||||||
# Extract, Clean Message from Claude's Response
|
# Extract, Clean Message from Claude's Response
|
||||||
try:
|
try:
|
||||||
response = clean_json(response)
|
response = clean_json(response)
|
||||||
response = json.loads(response)
|
response = pyjson5.loads(response)
|
||||||
response = [q.strip() for q in response["queries"] if q.strip()]
|
response = [q.strip() for q in response["queries"] if q.strip()]
|
||||||
if not isinstance(response, list) or not response:
|
if not isinstance(response, list) or not response:
|
||||||
logger.error(f"Invalid response for constructing subqueries: {response}")
|
logger.error(f"Invalid response for constructing subqueries: {response}")
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
import pyjson5
|
||||||
from langchain.schema import ChatMessage
|
from langchain.schema import ChatMessage
|
||||||
|
|
||||||
from khoj.database.models import Agent, ChatModelOptions, KhojUser
|
from khoj.database.models import Agent, ChatModelOptions, KhojUser
|
||||||
|
@ -104,7 +103,7 @@ def extract_questions_gemini(
|
||||||
# Extract, Clean Message from Gemini's Response
|
# Extract, Clean Message from Gemini's Response
|
||||||
try:
|
try:
|
||||||
response = clean_json(response)
|
response = clean_json(response)
|
||||||
response = json.loads(response)
|
response = pyjson5.loads(response)
|
||||||
response = [q.strip() for q in response["queries"] if q.strip()]
|
response = [q.strip() for q in response["queries"] if q.strip()]
|
||||||
if not isinstance(response, list) or not response:
|
if not isinstance(response, list) or not response:
|
||||||
logger.error(f"Invalid response for constructing subqueries: {response}")
|
logger.error(f"Invalid response for constructing subqueries: {response}")
|
||||||
|
|
|
@ -5,6 +5,7 @@ from datetime import datetime, timedelta
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from typing import Any, Iterator, List, Optional, Union
|
from typing import Any, Iterator, List, Optional, Union
|
||||||
|
|
||||||
|
import pyjson5
|
||||||
from langchain.schema import ChatMessage
|
from langchain.schema import ChatMessage
|
||||||
from llama_cpp import Llama
|
from llama_cpp import Llama
|
||||||
|
|
||||||
|
@ -13,6 +14,7 @@ from khoj.processor.conversation import prompts
|
||||||
from khoj.processor.conversation.offline.utils import download_model
|
from khoj.processor.conversation.offline.utils import download_model
|
||||||
from khoj.processor.conversation.utils import (
|
from khoj.processor.conversation.utils import (
|
||||||
ThreadedGenerator,
|
ThreadedGenerator,
|
||||||
|
clean_json,
|
||||||
commit_conversation_trace,
|
commit_conversation_trace,
|
||||||
generate_chatml_messages_with_context,
|
generate_chatml_messages_with_context,
|
||||||
messages_to_print,
|
messages_to_print,
|
||||||
|
@ -114,8 +116,8 @@ def extract_questions_offline(
|
||||||
|
|
||||||
# Extract and clean the chat model's response
|
# Extract and clean the chat model's response
|
||||||
try:
|
try:
|
||||||
response = response.strip(empty_escape_sequences)
|
response = clean_json(empty_escape_sequences)
|
||||||
response = json.loads(response)
|
response = pyjson5.loads(response)
|
||||||
questions = [q.strip() for q in response["queries"] if q.strip()]
|
questions = [q.strip() for q in response["queries"] if q.strip()]
|
||||||
questions = filter_questions(questions)
|
questions = filter_questions(questions)
|
||||||
except:
|
except:
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from typing import Dict, List, Optional
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
|
import pyjson5
|
||||||
from langchain.schema import ChatMessage
|
from langchain.schema import ChatMessage
|
||||||
|
|
||||||
from khoj.database.models import Agent, ChatModelOptions, KhojUser
|
from khoj.database.models import Agent, ChatModelOptions, KhojUser
|
||||||
|
@ -104,7 +104,7 @@ def extract_questions(
|
||||||
# Extract, Clean Message from GPT's Response
|
# Extract, Clean Message from GPT's Response
|
||||||
try:
|
try:
|
||||||
response = clean_json(response)
|
response = clean_json(response)
|
||||||
response = json.loads(response)
|
response = pyjson5.loads(response)
|
||||||
response = [q.strip() for q in response["queries"] if q.strip()]
|
response = [q.strip() for q in response["queries"] if q.strip()]
|
||||||
if not isinstance(response, list) or not response:
|
if not isinstance(response, list) or not response:
|
||||||
logger.error(f"Invalid response for constructing subqueries: {response}")
|
logger.error(f"Invalid response for constructing subqueries: {response}")
|
||||||
|
|
|
@ -30,11 +30,9 @@ You were created by Khoj Inc. with the following capabilities:
|
||||||
|
|
||||||
- You *CAN REMEMBER ALL NOTES and PERSONAL INFORMATION FOREVER* that the user ever shares with you.
|
- You *CAN REMEMBER ALL NOTES and PERSONAL INFORMATION FOREVER* that the user ever shares with you.
|
||||||
- Users can share files and other information with you using the Khoj Desktop, Obsidian or Emacs app. They can also drag and drop their files into the chat window.
|
- Users can share files and other information with you using the Khoj Desktop, Obsidian or Emacs app. They can also drag and drop their files into the chat window.
|
||||||
- Say "I don't know" or "I don't understand" if you don't know what to say or if you don't know the answer to a question.
|
|
||||||
- Make sure to use the specific LaTeX math mode delimiters for your response. LaTex math mode specific delimiters as following
|
- Make sure to use the specific LaTeX math mode delimiters for your response. LaTex math mode specific delimiters as following
|
||||||
- inline math mode : `\\(` and `\\)`
|
- inline math mode : `\\(` and `\\)`
|
||||||
- display math mode: insert linebreak after opening `$$`, `\\[` and before closing `$$`, `\\]`
|
- display math mode: insert linebreak after opening `$$`, `\\[` and before closing `$$`, `\\]`
|
||||||
- Ask crisp follow-up questions to get additional context, when the answer cannot be inferred from the provided notes or past conversations.
|
|
||||||
- Sometimes the user will share personal information that needs to be remembered, like an account ID or a residential address. These can be acknowledged with a simple "Got it" or "Okay".
|
- Sometimes the user will share personal information that needs to be remembered, like an account ID or a residential address. These can be acknowledged with a simple "Got it" or "Okay".
|
||||||
|
|
||||||
Today is {day_of_week}, {current_date} in UTC.
|
Today is {day_of_week}, {current_date} in UTC.
|
||||||
|
|
|
@ -5,6 +5,7 @@ import math
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
import queue
|
import queue
|
||||||
|
import re
|
||||||
import uuid
|
import uuid
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
@ -14,6 +15,7 @@ from time import perf_counter
|
||||||
from typing import Any, Callable, Dict, List, Optional
|
from typing import Any, Callable, Dict, List, Optional
|
||||||
|
|
||||||
import PIL.Image
|
import PIL.Image
|
||||||
|
import pyjson5
|
||||||
import requests
|
import requests
|
||||||
import tiktoken
|
import tiktoken
|
||||||
import yaml
|
import yaml
|
||||||
|
@ -590,6 +592,47 @@ def clean_code_python(code: str):
|
||||||
return code.strip().removeprefix("```python").removesuffix("```")
|
return code.strip().removeprefix("```python").removesuffix("```")
|
||||||
|
|
||||||
|
|
||||||
|
def load_complex_json(json_str):
|
||||||
|
"""
|
||||||
|
Preprocess a raw JSON string to escape unescaped double quotes within value strings,
|
||||||
|
while preserving the JSON structure and already escaped quotes.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def replace_unescaped_quotes(match):
|
||||||
|
# Get the content between colons and commas/end braces
|
||||||
|
content = match.group(1)
|
||||||
|
# Replace unescaped double, single quotes that aren't already escaped
|
||||||
|
# Uses negative lookbehind to avoid replacing already escaped quotes
|
||||||
|
# Replace " with \"
|
||||||
|
processed_dq = re.sub(r'(?<!\\)"', '\\"', content)
|
||||||
|
# Replace \' with \\'
|
||||||
|
processed_final = re.sub(r"(?<!\\)\\'", r"\\\\'", processed_dq)
|
||||||
|
return f': "{processed_final}"'
|
||||||
|
|
||||||
|
# Match content between : and either , or }
|
||||||
|
# This pattern looks for ': ' followed by any characters until , or }
|
||||||
|
pattern = r':\s*"(.*?)(?<!\\)"(?=[,}])'
|
||||||
|
|
||||||
|
# Process the JSON string
|
||||||
|
cleaned = clean_json(rf"{json_str}")
|
||||||
|
processed = re.sub(pattern, replace_unescaped_quotes, cleaned)
|
||||||
|
|
||||||
|
# See which json loader can load the processed JSON as valid
|
||||||
|
errors = []
|
||||||
|
json_loaders_to_try = [json.loads, pyjson5.loads]
|
||||||
|
for loads in json_loaders_to_try:
|
||||||
|
try:
|
||||||
|
return loads(processed)
|
||||||
|
except (json.JSONDecodeError, pyjson5.Json5Exception) as e:
|
||||||
|
errors.append(f"{type(e).__name__}: {str(e)}")
|
||||||
|
|
||||||
|
# If all loaders fail, raise the aggregated error
|
||||||
|
raise ValueError(
|
||||||
|
f"Failed to load JSON with errors: {'; '.join(errors)}\n\n"
|
||||||
|
f"While attempting to load this cleaned JSON:\n{processed}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def defilter_query(query: str):
|
def defilter_query(query: str):
|
||||||
"""Remove any query filters in query"""
|
"""Remove any query filters in query"""
|
||||||
defiltered_query = query
|
defiltered_query = query
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import base64
|
import base64
|
||||||
import datetime
|
import datetime
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
import os
|
import os
|
||||||
|
@ -15,8 +14,8 @@ from khoj.processor.conversation import prompts
|
||||||
from khoj.processor.conversation.utils import (
|
from khoj.processor.conversation.utils import (
|
||||||
ChatEvent,
|
ChatEvent,
|
||||||
clean_code_python,
|
clean_code_python,
|
||||||
clean_json,
|
|
||||||
construct_chat_history,
|
construct_chat_history,
|
||||||
|
load_complex_json,
|
||||||
)
|
)
|
||||||
from khoj.routers.helpers import send_message_to_model_wrapper
|
from khoj.routers.helpers import send_message_to_model_wrapper
|
||||||
from khoj.utils.helpers import is_none_or_empty, timer, truncate_code_context
|
from khoj.utils.helpers import is_none_or_empty, timer, truncate_code_context
|
||||||
|
@ -135,8 +134,7 @@ async def generate_python_code(
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validate that the response is a non-empty, JSON-serializable list
|
# Validate that the response is a non-empty, JSON-serializable list
|
||||||
response = clean_json(response)
|
response = load_complex_json(response)
|
||||||
response = json.loads(response)
|
|
||||||
code = response.get("code", "").strip()
|
code = response.get("code", "").strip()
|
||||||
input_files = response.get("input_files", [])
|
input_files = response.get("input_files", [])
|
||||||
input_links = response.get("input_links", [])
|
input_links = response.get("input_links", [])
|
||||||
|
|
|
@ -27,6 +27,7 @@ from typing import (
|
||||||
from urllib.parse import parse_qs, quote, unquote, urljoin, urlparse
|
from urllib.parse import parse_qs, quote, unquote, urljoin, urlparse
|
||||||
|
|
||||||
import cron_descriptor
|
import cron_descriptor
|
||||||
|
import pyjson5
|
||||||
import pytz
|
import pytz
|
||||||
import requests
|
import requests
|
||||||
from apscheduler.job import Job
|
from apscheduler.job import Job
|
||||||
|
@ -541,7 +542,7 @@ async def generate_online_subqueries(
|
||||||
# Validate that the response is a non-empty, JSON-serializable list
|
# Validate that the response is a non-empty, JSON-serializable list
|
||||||
try:
|
try:
|
||||||
response = clean_json(response)
|
response = clean_json(response)
|
||||||
response = json.loads(response)
|
response = pyjson5.loads(response)
|
||||||
response = {q.strip() for q in response["queries"] if q.strip()}
|
response = {q.strip() for q in response["queries"] if q.strip()}
|
||||||
if not isinstance(response, set) or not response or len(response) == 0:
|
if not isinstance(response, set) or not response or len(response) == 0:
|
||||||
logger.error(f"Invalid response for constructing subqueries: {response}. Returning original query: {q}")
|
logger.error(f"Invalid response for constructing subqueries: {response}. Returning original query: {q}")
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import json
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from typing import Callable, Dict, List, Optional
|
from typing import Callable, Dict, List, Optional
|
||||||
|
@ -10,10 +9,10 @@ from khoj.database.models import Agent, KhojUser
|
||||||
from khoj.processor.conversation import prompts
|
from khoj.processor.conversation import prompts
|
||||||
from khoj.processor.conversation.utils import (
|
from khoj.processor.conversation.utils import (
|
||||||
InformationCollectionIteration,
|
InformationCollectionIteration,
|
||||||
clean_json,
|
|
||||||
construct_chat_history,
|
construct_chat_history,
|
||||||
construct_iteration_history,
|
construct_iteration_history,
|
||||||
construct_tool_chat_history,
|
construct_tool_chat_history,
|
||||||
|
load_complex_json,
|
||||||
)
|
)
|
||||||
from khoj.processor.tools.online_search import read_webpages, search_online
|
from khoj.processor.tools.online_search import read_webpages, search_online
|
||||||
from khoj.processor.tools.run_code import run_code
|
from khoj.processor.tools.run_code import run_code
|
||||||
|
@ -106,8 +105,7 @@ async def apick_next_tool(
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = clean_json(response)
|
response = load_complex_json(response)
|
||||||
response = json.loads(response)
|
|
||||||
selected_tool = response.get("tool", None)
|
selected_tool = response.get("tool", None)
|
||||||
generated_query = response.get("query", None)
|
generated_query = response.get("query", None)
|
||||||
scratchpad = response.get("scratchpad", None)
|
scratchpad = response.get("scratchpad", None)
|
||||||
|
|
|
@ -134,3 +134,8 @@ def automations_config_page(
|
||||||
"request": request,
|
"request": request,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@web_client.get("/.well-known/assetlinks.json", response_class=FileResponse)
|
||||||
|
def assetlinks(request: Request):
|
||||||
|
return FileResponse(constants.assetlinks_file_path)
|
||||||
|
|
|
@ -5,6 +5,7 @@ app_root_directory = Path(__file__).parent.parent.parent
|
||||||
web_directory = app_root_directory / "khoj/interface/web/"
|
web_directory = app_root_directory / "khoj/interface/web/"
|
||||||
next_js_directory = app_root_directory / "khoj/interface/built/"
|
next_js_directory = app_root_directory / "khoj/interface/built/"
|
||||||
pypi_static_directory = app_root_directory / "khoj/interface/compiled/"
|
pypi_static_directory = app_root_directory / "khoj/interface/compiled/"
|
||||||
|
assetlinks_file_path = web_directory / ".well-known/assetlinks.json"
|
||||||
empty_escape_sequences = "\n|\r|\t| "
|
empty_escape_sequences = "\n|\r|\t| "
|
||||||
app_env_filepath = "~/.khoj/env"
|
app_env_filepath = "~/.khoj/env"
|
||||||
telemetry_server = "https://khoj.beta.haletic.com/v1/telemetry"
|
telemetry_server = "https://khoj.beta.haletic.com/v1/telemetry"
|
||||||
|
|
|
@ -3,8 +3,10 @@ import concurrent.futures
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from functools import partial
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
from textwrap import dedent
|
from textwrap import dedent
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
|
@ -24,13 +26,10 @@ logger = logging.getLogger(__name__)
|
||||||
KHOJ_URL = os.getenv("KHOJ_URL", "http://localhost:42110")
|
KHOJ_URL = os.getenv("KHOJ_URL", "http://localhost:42110")
|
||||||
KHOJ_CHAT_API_URL = f"{KHOJ_URL}/api/chat"
|
KHOJ_CHAT_API_URL = f"{KHOJ_URL}/api/chat"
|
||||||
KHOJ_API_KEY = os.getenv("KHOJ_API_KEY")
|
KHOJ_API_KEY = os.getenv("KHOJ_API_KEY")
|
||||||
KHOJ_MODE = os.getenv("KHOJ_MODE", "default") # E.g research, general, notes etc.
|
KHOJ_MODE = os.getenv("KHOJ_MODE", "default").lower() # E.g research, general, notes etc.
|
||||||
|
|
||||||
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY")
|
||||||
GEMINI_EVAL_MODEL = os.getenv("GEMINI_EVAL_MODEL", "gemini-1.5-pro-002")
|
GEMINI_EVAL_MODEL = os.getenv("GEMINI_EVAL_MODEL", "gemini-1.5-pro-002")
|
||||||
GEMINI_API_URL = (
|
|
||||||
f"https://generativelanguage.googleapis.com/v1beta/models/{GEMINI_EVAL_MODEL}:generateContent?key={GEMINI_API_KEY}"
|
|
||||||
)
|
|
||||||
|
|
||||||
SAMPLE_SIZE = os.getenv("SAMPLE_SIZE") # Number of examples to evaluate
|
SAMPLE_SIZE = os.getenv("SAMPLE_SIZE") # Number of examples to evaluate
|
||||||
RANDOMIZE = os.getenv("RANDOMIZE", "false").lower() == "true" # Randomize examples
|
RANDOMIZE = os.getenv("RANDOMIZE", "false").lower() == "true" # Randomize examples
|
||||||
|
@ -128,6 +127,99 @@ def load_simpleqa_dataset():
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def load_gpqa_dataset():
|
||||||
|
"""
|
||||||
|
Load the Google GPQA benchmark dataset from HuggingFace
|
||||||
|
|
||||||
|
GPQA is a benchmark dataset to evaluate retrieval and answering capabilities of agents.
|
||||||
|
It contains ~800 requiring multi-hop retrieval and reasoning across various topics.
|
||||||
|
|
||||||
|
### Data Fields
|
||||||
|
- Prompt: The question to be answered
|
||||||
|
- Answer: The ground truth answer
|
||||||
|
- reasoning_types: The type of reasoning required to answer the question
|
||||||
|
"""
|
||||||
|
import random
|
||||||
|
|
||||||
|
def format_multiple_choice_question(row: Dict) -> tuple[str, str]:
|
||||||
|
"""
|
||||||
|
Create GPQA multi-choice prompt from shuffled answer choices and question.
|
||||||
|
Refer: https://github.com/openai/simple-evals/blob/a8e85cc8a5dea497d915f870895250e07f9cc737/common.py#L12
|
||||||
|
|
||||||
|
Returns formatted prompt and correct answer letter.
|
||||||
|
"""
|
||||||
|
# Gather choices
|
||||||
|
choices = [
|
||||||
|
row["Incorrect Answer 1"],
|
||||||
|
row["Incorrect Answer 2"],
|
||||||
|
row["Incorrect Answer 3"],
|
||||||
|
row["Correct Answer"],
|
||||||
|
]
|
||||||
|
# Shuffle choices
|
||||||
|
random.shuffle(choices)
|
||||||
|
|
||||||
|
# Get correct answer letter
|
||||||
|
correct_index = choices.index(row["Correct Answer"])
|
||||||
|
correct_letter = "ABCD"[correct_index]
|
||||||
|
|
||||||
|
prompt = f"""
|
||||||
|
Answer the following multiple choice question. Answer should be of the following format: 'Answer: $LETTER' (without quotes) where LETTER is one of ABCD. Think step by step before answering.
|
||||||
|
|
||||||
|
{row["Question"]}
|
||||||
|
|
||||||
|
A) {choices[0]}
|
||||||
|
B) {choices[1]}
|
||||||
|
C) {choices[2]}
|
||||||
|
D) {choices[3]}
|
||||||
|
""".strip()
|
||||||
|
|
||||||
|
return prompt, correct_letter
|
||||||
|
|
||||||
|
try:
|
||||||
|
dataset = load_dataset("Idavidrein/gpqa", "gpqa_diamond", split="train")
|
||||||
|
|
||||||
|
# Create multi-choice q&a prompt from choices and correct answer
|
||||||
|
prompts_and_answers = [format_multiple_choice_question(row) for row in dataset]
|
||||||
|
|
||||||
|
# Normalize dataset to FRAMES format
|
||||||
|
dataset = dataset.rename_columns({"Subdomain": "reasoning_types"})
|
||||||
|
dataset = dataset.add_column("Prompt", [p[0] for p in prompts_and_answers])
|
||||||
|
dataset = dataset.add_column("Answer", [p[1] for p in prompts_and_answers])
|
||||||
|
|
||||||
|
# Sample and shuffle dataset if configured
|
||||||
|
dataset = dataset.shuffle() if RANDOMIZE else dataset
|
||||||
|
dataset = dataset[: int(SAMPLE_SIZE)] if SAMPLE_SIZE else dataset
|
||||||
|
|
||||||
|
return dataset
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error loading dataset: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def load_math500_dataset():
|
||||||
|
"""
|
||||||
|
Load and format the MATH500 dataset to match the evaluation script's structure.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
sample_size (int, optional): Number of samples to include. Defaults to None (use full dataset).
|
||||||
|
randomize (bool, optional): Whether to randomize the dataset. Defaults to False.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dataset: Formatted HuggingFace Dataset.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# Load the MATH500 dataset from HuggingFace
|
||||||
|
dataset = load_dataset("HuggingFaceH4/MATH-500", split="test")
|
||||||
|
dataset = dataset.rename_columns({"problem": "Prompt", "answer": "Answer", "subject": "reasoning_types"})
|
||||||
|
dataset = dataset.shuffle() if RANDOMIZE else dataset
|
||||||
|
dataset = dataset.select(range(int(SAMPLE_SIZE))) if SAMPLE_SIZE else dataset
|
||||||
|
|
||||||
|
return dataset
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error loading and formatting MATH500 dataset: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_agent_response(prompt: str) -> Dict[str, Any]:
|
def get_agent_response(prompt: str) -> Dict[str, Any]:
|
||||||
"""Get response from the Khoj API"""
|
"""Get response from the Khoj API"""
|
||||||
# Set headers
|
# Set headers
|
||||||
|
@ -152,7 +244,30 @@ def get_agent_response(prompt: str) -> Dict[str, Any]:
|
||||||
return {"response": "", "usage": {}}
|
return {"response": "", "usage": {}}
|
||||||
|
|
||||||
|
|
||||||
def evaluate_response(query: str, agent_response: str, ground_truth: str) -> tuple[bool | None, str, float]:
|
def evaluate_response_with_mcq_match(
|
||||||
|
query: str, agent_response: str, ground_truth: str
|
||||||
|
) -> tuple[bool | None, str, float]:
|
||||||
|
"""Evaluate Khoj response against benchmark ground truth using string matching"""
|
||||||
|
try:
|
||||||
|
# Extract answer from agent response
|
||||||
|
answer_pattern_multichoice = r"(?i)Answer\s*:\s*([A-D])"
|
||||||
|
match = re.search(answer_pattern_multichoice, agent_response)
|
||||||
|
extracted_answer = match.group(1) if match else None
|
||||||
|
|
||||||
|
# Check if extracted answer matches ground truth
|
||||||
|
decision = extracted_answer == ground_truth
|
||||||
|
explanation = f"Agent response {'matches' if decision else 'does not match'} ground truth {ground_truth}"
|
||||||
|
|
||||||
|
# Return decision, explanation and cost in structured form
|
||||||
|
return decision, explanation, 0.0
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error in evaluation: {e}")
|
||||||
|
return None, f"Evaluation failed: {str(e)}", 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate_response_with_gemini(
|
||||||
|
query: str, agent_response: str, ground_truth: str, eval_model=GEMINI_EVAL_MODEL
|
||||||
|
) -> tuple[bool | None, str, float]:
|
||||||
"""Evaluate Khoj response against benchmark ground truth using Gemini"""
|
"""Evaluate Khoj response against benchmark ground truth using Gemini"""
|
||||||
evaluation_prompt = f"""
|
evaluation_prompt = f"""
|
||||||
Compare the following agent response with the ground truth answer.
|
Compare the following agent response with the ground truth answer.
|
||||||
|
@ -166,10 +281,13 @@ def evaluate_response(query: str, agent_response: str, ground_truth: str) -> tup
|
||||||
Provide your evaluation in the following json format:
|
Provide your evaluation in the following json format:
|
||||||
{"explanation:" "[How you made the decision?)", "decision:" "(TRUE if response contains key information, FALSE otherwise)"}
|
{"explanation:" "[How you made the decision?)", "decision:" "(TRUE if response contains key information, FALSE otherwise)"}
|
||||||
"""
|
"""
|
||||||
|
gemini_api_url = (
|
||||||
|
f"https://generativelanguage.googleapis.com/v1beta/models/{eval_model}:generateContent?key={GEMINI_API_KEY}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.post(
|
response = requests.post(
|
||||||
GEMINI_API_URL,
|
gemini_api_url,
|
||||||
headers={"Content-Type": "application/json"},
|
headers={"Content-Type": "application/json"},
|
||||||
json={
|
json={
|
||||||
"contents": [{"parts": [{"text": evaluation_prompt}]}],
|
"contents": [{"parts": [{"text": evaluation_prompt}]}],
|
||||||
|
@ -182,7 +300,7 @@ def evaluate_response(query: str, agent_response: str, ground_truth: str) -> tup
|
||||||
# Update cost of evaluation
|
# Update cost of evaluation
|
||||||
input_tokens = response_json["usageMetadata"]["promptTokenCount"]
|
input_tokens = response_json["usageMetadata"]["promptTokenCount"]
|
||||||
ouput_tokens = response_json["usageMetadata"]["candidatesTokenCount"]
|
ouput_tokens = response_json["usageMetadata"]["candidatesTokenCount"]
|
||||||
cost = get_cost_of_chat_message(GEMINI_EVAL_MODEL, input_tokens, ouput_tokens)
|
cost = get_cost_of_chat_message(eval_model, input_tokens, ouput_tokens)
|
||||||
|
|
||||||
# Parse evaluation response
|
# Parse evaluation response
|
||||||
eval_response: dict[str, str] = json.loads(
|
eval_response: dict[str, str] = json.loads(
|
||||||
|
@ -200,7 +318,7 @@ def evaluate_response(query: str, agent_response: str, ground_truth: str) -> tup
|
||||||
return None, f"Evaluation failed: {str(e)}", 0.0
|
return None, f"Evaluation failed: {str(e)}", 0.0
|
||||||
|
|
||||||
|
|
||||||
def process_batch(batch, batch_start, results, dataset_length):
|
def process_batch(batch, batch_start, results, dataset_length, response_evaluator):
|
||||||
global running_cost
|
global running_cost
|
||||||
for idx, (prompt, answer, reasoning_type) in enumerate(batch):
|
for idx, (prompt, answer, reasoning_type) in enumerate(batch):
|
||||||
current_index = batch_start + idx
|
current_index = batch_start + idx
|
||||||
|
@ -219,7 +337,7 @@ def process_batch(batch, batch_start, results, dataset_length):
|
||||||
decision = None
|
decision = None
|
||||||
explanation = "Agent response is empty. This maybe due to a service error."
|
explanation = "Agent response is empty. This maybe due to a service error."
|
||||||
else:
|
else:
|
||||||
decision, explanation, eval_cost = evaluate_response(prompt, agent_response, answer)
|
decision, explanation, eval_cost = response_evaluator(prompt, agent_response, answer)
|
||||||
|
|
||||||
# Store results
|
# Store results
|
||||||
results.append(
|
results.append(
|
||||||
|
@ -292,7 +410,7 @@ def parse_args():
|
||||||
"--dataset",
|
"--dataset",
|
||||||
"-d",
|
"-d",
|
||||||
default="frames",
|
default="frames",
|
||||||
choices=["frames", "simpleqa"],
|
choices=["frames", "simpleqa", "gpqa", "math500"],
|
||||||
help="Dataset to use for evaluation (default: frames)",
|
help="Dataset to use for evaluation (default: frames)",
|
||||||
)
|
)
|
||||||
return parser.parse_args()
|
return parser.parse_args()
|
||||||
|
@ -309,12 +427,24 @@ def main():
|
||||||
dataset = load_frames_dataset()
|
dataset = load_frames_dataset()
|
||||||
elif args.dataset == "simpleqa":
|
elif args.dataset == "simpleqa":
|
||||||
dataset = load_simpleqa_dataset()
|
dataset = load_simpleqa_dataset()
|
||||||
|
elif args.dataset == "gpqa":
|
||||||
|
dataset = load_gpqa_dataset()
|
||||||
|
elif args.dataset == "math500":
|
||||||
|
dataset = load_math500_dataset()
|
||||||
if dataset is None:
|
if dataset is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Initialize variables
|
# Initialize variables
|
||||||
results = []
|
results = []
|
||||||
dataset_length = len(dataset["Prompt"])
|
dataset_length = len(dataset["Prompt"])
|
||||||
|
if args.dataset == "gpqa":
|
||||||
|
response_evaluator = evaluate_response_with_mcq_match
|
||||||
|
elif args.dataset == "math500":
|
||||||
|
response_evaluator = partial(
|
||||||
|
evaluate_response_with_gemini, eval_model=os.getenv("GEMINI_EVAL_MODEL", "gemini-1.5-flash-002")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
response_evaluator = evaluate_response_with_gemini
|
||||||
|
|
||||||
# Process examples in batches
|
# Process examples in batches
|
||||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||||
|
@ -326,7 +456,9 @@ def main():
|
||||||
dataset["Answer"][i : i + BATCH_SIZE],
|
dataset["Answer"][i : i + BATCH_SIZE],
|
||||||
dataset["reasoning_types"][i : i + BATCH_SIZE],
|
dataset["reasoning_types"][i : i + BATCH_SIZE],
|
||||||
)
|
)
|
||||||
futures.append(executor.submit(process_batch, batch, batch_start, results, dataset_length))
|
futures.append(
|
||||||
|
executor.submit(process_batch, batch, batch_start, results, dataset_length, response_evaluator)
|
||||||
|
)
|
||||||
|
|
||||||
# Wait for all futures to complete
|
# Wait for all futures to complete
|
||||||
concurrent.futures.wait(futures)
|
concurrent.futures.wait(futures)
|
||||||
|
|
|
@ -104,6 +104,18 @@ class TestTruncateMessage:
|
||||||
assert truncated_chat_history[0] != copy_big_chat_message
|
assert truncated_chat_history[0] != copy_big_chat_message
|
||||||
|
|
||||||
|
|
||||||
|
def test_load_complex_raw_json_string():
|
||||||
|
# Arrange
|
||||||
|
raw_json = r"""{"key": "value with unescaped " and unescaped \' and escaped \" and escaped \\'"}"""
|
||||||
|
expeced_json = {"key": "value with unescaped \" and unescaped \\' and escaped \" and escaped \\'"}
|
||||||
|
|
||||||
|
# Act
|
||||||
|
parsed_json = utils.load_complex_json(raw_json)
|
||||||
|
|
||||||
|
# Assert
|
||||||
|
assert parsed_json == expeced_json
|
||||||
|
|
||||||
|
|
||||||
def generate_content(count):
|
def generate_content(count):
|
||||||
return " ".join([f"{index}" for index, _ in enumerate(range(count))])
|
return " ".join([f"{index}" for index, _ in enumerate(range(count))])
|
||||||
|
|
||||||
|
|
|
@ -98,5 +98,8 @@
|
||||||
"1.30.4": "0.15.0",
|
"1.30.4": "0.15.0",
|
||||||
"1.30.5": "0.15.0",
|
"1.30.5": "0.15.0",
|
||||||
"1.30.6": "0.15.0",
|
"1.30.6": "0.15.0",
|
||||||
"1.30.7": "0.15.0"
|
"1.30.7": "0.15.0",
|
||||||
|
"1.30.8": "0.15.0",
|
||||||
|
"1.30.9": "0.15.0",
|
||||||
|
"1.30.10": "0.15.0"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue