[pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
This commit is contained in:
pre-commit-ci[bot] 2024-08-06 13:55:15 +00:00
parent e3a4ce34e9
commit 8cdd7d5efa
262 changed files with 364 additions and 308 deletions

View File

@ -1,4 +1,4 @@
name: QUIVR INTERNAL ONLY - Epic
name: QUIVR INTERNAL ONLY - Epic
description: Use this form for epics.
title: "[Epic]: "
labels: ["epic"]

View File

@ -71,4 +71,3 @@
# JWT_SECRET_KEY: ${{secrets.JWT_SECRET_KEY}}
# CI_TEST_API_KEY: ${{secrets.CI_TEST_API_KEY}}
# CELERY_BROKER_URL: ${{secrets.CELERY_BROKER_URL}}

View File

@ -17,4 +17,4 @@ jobs:
steps:
- uses: amannn/action-semantic-pull-request@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -67,4 +67,4 @@ jobs:
# tags: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}, ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:latest, ghcr.io/quivrhq/quivr:latest, stangirard/quivr-backend-prebuilt:latest, stangirard/quivr-backend-prebuilt:${{ env.IMAGE_TAG }}
tags: ghcr.io/quivrhq/quivr:latest, stangirard/quivr-backend-prebuilt:latest, stangirard/quivr-backend-prebuilt:${{ env.IMAGE_TAG }}
cache-from: type=gha
cache-to: type=gha,mode=max
cache-to: type=gha,mode=max

View File

@ -32,7 +32,7 @@ jobs:
with:
path: backend/core
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
deploy:
if: needs.release-please.outputs.release_created == 'true'
@ -62,4 +62,4 @@ jobs:
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: backend/core/dist
packages_dir: backend/core/dist

View File

@ -2,13 +2,13 @@ on:
push:
branches:
- main
permissions:
contents: write
pull-requests: write
name: release-please
jobs:
release-please:
runs-on: ubuntu-latest
@ -19,4 +19,4 @@ jobs:
changelog-notes-type: github
package-name: release-please-action
bump-patch-for-minor-pre-major: true
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}
token: ${{ secrets.RELEASE_PLEASE_TOKEN }}

View File

@ -43,4 +43,4 @@ jobs:
context: ./backend/
platforms: ${{ matrix.platform }}
cache-from: type=gha
cache-to: type=gha,mode=max
cache-to: type=gha,mode=max

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
with:
submodules: 'true'
- name: Install Vercel CLI
run: npm install --global vercel@latest
@ -20,4 +20,4 @@ jobs:
- name: Build Project Artifacts
run: vercel build --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }}
run: vercel deploy --prebuilt --token=${{ secrets.VERCEL_TOKEN }}

View File

@ -5,16 +5,16 @@ env:
on:
push:
# Pattern matched against refs/tags
tags:
tags:
- '*' # Push events to every tag not containing /
jobs:
Deploy-Production:
environment: production
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
with:
submodules: 'true'
- name: Install Vercel CLI
run: npm install --global vercel@latest
@ -23,4 +23,4 @@ jobs:
- name: Build Project Artifacts
run: vercel build --prod --token=${{ secrets.VERCEL_TOKEN }}
- name: Deploy Project Artifacts to Vercel
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}
run: vercel deploy --prebuilt --prod --token=${{ secrets.VERCEL_TOKEN }}

View File

@ -1,4 +1,4 @@
{
"backend/core": "0.0.13",
".": "0.0.293"
}
}

View File

@ -7,4 +7,4 @@
"inlang.vs-code-extension",
"denoland.vscode-deno"
]
}
}

2
.vscode/launch.json vendored
View File

@ -38,4 +38,4 @@
"envFile": "${workspaceFolder}/.env"
}
]
}
}

View File

@ -54,4 +54,4 @@
"reportUnusedImport": "warning",
"reportGeneralTypeIssues": "warning"
}
}
}

View File

@ -205,4 +205,4 @@
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
limitations under the License.

View File

@ -18,7 +18,7 @@ dev-saas-back:
docker compose -f docker-compose-dev-only-back-saas-supabase.yml up --build backend-core
dev-stan:
docker compose -f docker-compose-no-frontend.dev.yml up --build
docker compose -f docker-compose-no-frontend.dev.yml up --build
prod:
docker compose build backend-core
@ -35,4 +35,4 @@ front:
cd frontend && yarn build && yarn start
test:
cd backend/core && ./scripts/run_tests.sh
cd backend/core && ./scripts/run_tests.sh

View File

@ -88,7 +88,7 @@ You can find the installation video [here](https://www.youtube.com/watch?v=cXBa6
```bash
cd backend && supabase start
```
and then
and then
```bash
cd ../
docker compose pull

View File

@ -21,4 +21,4 @@
"justMyCode": true
}
]
}
}

View File

@ -1,4 +1,5 @@
from celery.result import AsyncResult
from quivr_api.celery_config import celery
from quivr_api.logger import get_logger
from quivr_api.modules.knowledge.dto.inputs import KnowledgeStatus
@ -39,9 +40,9 @@ def notifier(app):
NotificationUpdatableProperties(
status=NotificationsStatusEnum.ERROR,
description=(
f"An error occurred while processing the file"
"An error occurred while processing the file"
if task_name == "process_file_and_notify"
else f"An error occurred while processing the URL"
else "An error occurred while processing the URL"
),
),
)

View File

@ -5,6 +5,7 @@ from uuid import UUID
from celery.schedules import crontab
from pytz import timezone
from quivr_api.celery_config import celery
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth.auth_bearer import AuthBearer

View File

@ -4,7 +4,7 @@ from logging.handlers import RotatingFileHandler
from colorlog import (
ColoredFormatter,
) # You need to install this package: pip install colorlog
)
def get_logger(logger_name, log_file="application.log"):

View File

@ -7,6 +7,9 @@ from dotenv import load_dotenv # type: ignore
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import HTMLResponse, JSONResponse
from pyinstrument import Profiler
from sentry_sdk.integrations.fastapi import FastApiIntegration
from sentry_sdk.integrations.starlette import StarletteIntegration
from quivr_api.logger import get_logger
from quivr_api.middlewares.cors import add_cors_middleware
from quivr_api.modules.analytics.controller.analytics_routes import analytics_router
@ -26,8 +29,6 @@ from quivr_api.packages.utils import handle_request_validation_error
from quivr_api.packages.utils.telemetry import maybe_send_telemetry
from quivr_api.routes.crawl_routes import crawl_router
from quivr_api.routes.subscription_routes import subscription_router
from sentry_sdk.integrations.fastapi import FastApiIntegration
from sentry_sdk.integrations.starlette import StarletteIntegration
load_dotenv()

View File

@ -3,6 +3,7 @@ from typing import Optional
from fastapi import Depends, HTTPException, Request
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
from quivr_api.middlewares.auth.jwt_token_handler import (
decode_access_token,
verify_token,
@ -57,7 +58,8 @@ class AuthBearer(HTTPBearer):
def get_test_user(self) -> UserIdentity:
return UserIdentity(
email="admin@quivr.app", id="39418e3b-0258-4452-af60-7acfcc1263ff" # type: ignore
email="admin@quivr.app",
id="39418e3b-0258-4452-af60-7acfcc1263ff", # type: ignore
) # replace with test user information

View File

@ -4,6 +4,7 @@ from typing import Optional
from jose import jwt
from jose.exceptions import JWTError
from quivr_api.modules.user.entity.user_identity import UserIdentity
SECRET_KEY = os.environ.get("JWT_SECRET_KEY")

View File

@ -1,6 +1,7 @@
from uuid import UUID
from pydantic import BaseModel, ConfigDict
from quivr_api.logger import get_logger
logger = get_logger(__name__)

View File

@ -7,11 +7,12 @@ from langchain_community.vectorstores.supabase import SupabaseVectorStore
from langchain_openai import OpenAIEmbeddings
from posthog import Posthog
from pydantic_settings import BaseSettings, SettingsConfigDict
from quivr_api.logger import get_logger
from quivr_api.models.databases.supabase.supabase import SupabaseDB
from sqlalchemy import Engine, create_engine
from supabase.client import Client, create_client
from quivr_api.logger import get_logger
from quivr_api.models.databases.supabase.supabase import SupabaseDB
logger = get_logger(__name__)

View File

@ -1,6 +1,7 @@
from uuid import UUID
from fastapi import APIRouter, Depends, Query
from quivr_api.middlewares.auth.auth_bearer import AuthBearer, get_current_user
from quivr_api.modules.analytics.entity.analytics import Range
from quivr_api.modules.analytics.service.analytics_service import AnalyticsService

View File

@ -1,16 +1,20 @@
from datetime import date
from enum import IntEnum
from typing import List
from pydantic import BaseModel
from datetime import date
class Range(IntEnum):
WEEK = 7
MONTH = 30
QUARTER = 90
class Usage(BaseModel):
date: date
usage_count: int
class BrainsUsages(BaseModel):
usages: List[Usage]
usages: List[Usage]

View File

@ -11,5 +11,4 @@ class AnalyticsService:
self.repository = Analytics()
def get_brains_usages(self, user_id, graph_range, brain_id=None):
return self.repository.get_brains_usages(user_id, graph_range, brain_id)

View File

@ -3,6 +3,7 @@ from typing import List
from uuid import uuid4
from fastapi import APIRouter, Depends
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.api_key.dto.outputs import ApiKeyInfo

View File

@ -1,6 +1,7 @@
from datetime import datetime
from fastapi import HTTPException
from quivr_api.logger import get_logger
from quivr_api.modules.api_key.repository.api_key_interface import ApiKeysInterface
from quivr_api.modules.api_key.repository.api_keys import ApiKeys

View File

@ -1,6 +1,7 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException, UploadFile
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.assistant.dto.inputs import InputAssistant

View File

@ -1,5 +1,6 @@
from bs4 import BeautifulSoup as Soup
from langchain_community.document_loaders.recursive_url_loader import RecursiveUrlLoader
from quivr_api.logger import get_logger
from quivr_api.modules.assistant.dto.outputs import (
AssistantOutput,
@ -15,7 +16,6 @@ logger = get_logger(__name__)
class CrawlerAssistant(ITO):
def __init__(
self,
**kwargs,
@ -25,7 +25,6 @@ class CrawlerAssistant(ITO):
)
async def process_assistant(self):
url = self.url
loader = RecursiveUrlLoader(
url=url, max_depth=2, extractor=lambda x: Soup(x, "html.parser").text

View File

@ -11,6 +11,7 @@ from langchain_community.chat_models import ChatLiteLLM
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate, PromptTemplate
from llama_parse import LlamaParse
from quivr_api.logger import get_logger
from quivr_api.modules.assistant.dto.inputs import InputAssistant
from quivr_api.modules.assistant.dto.outputs import (
@ -32,7 +33,6 @@ logger = get_logger(__name__)
class DifferenceAssistant(ITO):
def __init__(
self,
input: InputAssistant,
@ -69,7 +69,6 @@ class DifferenceAssistant(ITO):
return True
async def process_assistant(self):
document_1 = self.files[0]
document_2 = self.files[1]

View File

@ -9,6 +9,8 @@ from typing import List, Optional
from fastapi import UploadFile
from pydantic import BaseModel
from unidecode import unidecode
from quivr_api.logger import get_logger
from quivr_api.models.settings import SendEmailSettings
from quivr_api.modules.assistant.dto.inputs import InputAssistant
@ -18,7 +20,6 @@ from quivr_api.modules.upload.controller.upload_routes import upload_file
from quivr_api.modules.user.entity.user_identity import UserIdentity
from quivr_api.modules.user.service.user_usage import UserUsage
from quivr_api.packages.emails.send_email import send_email
from unidecode import unidecode
logger = get_logger(__name__)
@ -90,23 +91,23 @@ class ITO(BaseModel):
body = f"""
<div style="text-align: center;">
<img src="https://quivr-cms.s3.eu-west-3.amazonaws.com/logo_quivr_white_7e3c72620f.png" alt="Quivr Logo" style="width: 100px; height: 100px; border-radius: 50%; margin: 0 auto; display: block;">
<p>Quivr's ingestion process has been completed. The processed file is attached.</p>
<p><strong>Task:</strong> {task_name}</p>
<p><strong>Output:</strong> {custom_message}</p>
<br />
</div>
"""
if brain_id:
body += f"<div style='text-align: center;'>You can find the file <a href='{domain_quivr}studio/{brain_id}'>here</a>.</div> <br />"
body += f"""
body += """
<div style="text-align: center;">
<p>Please let us know if you have any questions or need further assistance.</p>
<p> The Quivr Team </p>
</div>
"""

View File

@ -12,6 +12,7 @@ from langchain_community.chat_models import ChatLiteLLM
from langchain_community.document_loaders import UnstructuredPDFLoader
from langchain_core.prompts import PromptTemplate
from langchain_text_splitters import CharacterTextSplitter
from quivr_api.logger import get_logger
from quivr_api.modules.assistant.dto.inputs import InputAssistant
from quivr_api.modules.assistant.dto.outputs import (
@ -29,7 +30,6 @@ logger = get_logger(__name__)
class SummaryAssistant(ITO):
def __init__(
self,
input: InputAssistant,
@ -69,7 +69,6 @@ class SummaryAssistant(ITO):
return True
async def process_assistant(self):
try:
self.increase_usage_user()
except Exception as e:
@ -94,7 +93,7 @@ class SummaryAssistant(ITO):
map_template = """The following is a document that has been divided into multiple sections:
{docs}
Please carefully analyze each section and identify the following:
1. Main Themes: What are the overarching ideas or topics in this section?
@ -113,7 +112,7 @@ class SummaryAssistant(ITO):
{docs}
Take these and distill it into a final, consolidated summary of the document. Make sure to include the main themes, key points, and important information such as data, quotes,people and specific events.
Use markdown such as bold, italics, underlined. For example, **bold**, *italics*, and _underlined_ to highlight key points.
Please provide the final summary with sections using bold headers.
Please provide the final summary with sections using bold headers.
Sections should always be Summary and Key Points, but feel free to add more sections as needed.
Always use bold text for the sections headers.
Keep the same language as the documents.

View File

@ -60,7 +60,6 @@ class PDFGenerator(FPDF):
self.cell(0, 10, "Github", 0, 1, "C", link="https://github.com/quivrhq/quivr")
def chapter_body(self):
self.set_font("DejaVu", "", 12)
self.multi_cell(0, 10, self.pdf_model.content, markdown=True)
self.ln()
@ -74,7 +73,7 @@ if __name__ == "__main__":
pdf_model = PDFModel(
title="Summary of Legal Services Rendered by Orrick",
content="""
**Summary:**
**Summary:**
The document is an invoice from Quivr Technologies, Inc. for legal services provided to client YC W24, related to initial corporate work. The total fees and disbursements amount to $8,345.00 for services rendered through February 29, 2024. The invoice includes specific instructions for payment remittance and contact information for inquiries. Online payment through e-billexpress.com is also an option.
**Key Points:**

View File

@ -5,7 +5,6 @@ from quivr_api.modules.assistant.entity.assistant import AssistantEntity
class AssistantInterface(ABC):
@abstractmethod
def get_all_assistants(self) -> List[AssistantEntity]:
"""

View File

@ -3,11 +3,12 @@ from uuid import UUID
from fastapi import HTTPException
from pydantic import BaseModel
from quivr_api.modules.base_uuid_entity import BaseUUIDModel
from sqlalchemy import exc
from sqlmodel import SQLModel, col, select
from sqlmodel.ext.asyncio.session import AsyncSession
from quivr_api.modules.base_uuid_entity import BaseUUIDModel
ModelType = TypeVar("ModelType", bound=BaseUUIDModel)
CreateSchema = TypeVar("CreateSchema", bound=BaseModel)
UpdateSchema = TypeVar("UpdateSchema", bound=BaseModel)

View File

@ -1,6 +1,7 @@
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Request
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth.auth_bearer import AuthBearer, get_current_user
from quivr_api.modules.brain.dto.inputs import (

View File

@ -2,6 +2,7 @@ from typing import Optional
from uuid import UUID
from pydantic import BaseModel
from quivr_api.logger import get_logger
from quivr_api.modules.brain.entity.brain_entity import BrainType
from quivr_api.modules.brain.entity.integration_brain import IntegrationType

View File

@ -4,19 +4,19 @@ from typing import List, Optional
from uuid import UUID
from pydantic import BaseModel
# from sqlmodel import Enum as PGEnum
from sqlalchemy.dialects.postgresql import ENUM as PGEnum
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlmodel import TIMESTAMP, Column, Field, Relationship, SQLModel, text
from sqlmodel import UUID as PGUUID
from quivr_api.modules.brain.entity.integration_brain import (
IntegrationDescriptionEntity,
IntegrationEntity,
)
from quivr_api.modules.prompt.entity.prompt import Prompt
# from sqlmodel import Enum as PGEnum
from sqlalchemy.dialects.postgresql import ENUM as PGEnum
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlmodel import TIMESTAMP
from sqlmodel import UUID as PGUUID
from sqlmodel import Column, Field, Relationship, SQLModel, text
class BrainType(str, Enum):
doc = "doc"

View File

@ -11,6 +11,7 @@ from langchain_core.prompts.chat import (
SystemMessagePromptTemplate,
)
from langchain_core.prompts.prompt import PromptTemplate
from quivr_api.logger import get_logger
from quivr_api.modules.brain.knowledge_brain_qa import KnowledgeBrainQA
from quivr_api.modules.chat.dto.chats import ChatQuestion
@ -60,7 +61,7 @@ class BigBrain(KnowledgeBrainQA):
CHAT_COMBINE_PROMPT = ChatPromptTemplate.from_messages(messages)
### Question prompt
question_prompt_template = """Use the following portion of a long document to see if any of the text is relevant to answer the question.
question_prompt_template = """Use the following portion of a long document to see if any of the text is relevant to answer the question.
Return any relevant text verbatim. Return the answer in the same language as the question. If the answer is not in the text, just say nothing in the same language as the question.
{context}
Question: {question}

View File

@ -4,6 +4,7 @@ from uuid import UUID
from langchain_community.chat_models import ChatLiteLLM
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from quivr_api.modules.brain.knowledge_brain_qa import KnowledgeBrainQA
from quivr_api.modules.chat.dto.chats import ChatQuestion

View File

@ -10,6 +10,7 @@ from langchain_core.tools import BaseTool
from langchain_openai import ChatOpenAI
from langgraph.graph import END, StateGraph
from langgraph.prebuilt import ToolExecutor, ToolInvocation
from quivr_api.logger import get_logger
from quivr_api.modules.brain.knowledge_brain_qa import KnowledgeBrainQA
from quivr_api.modules.chat.dto.chats import ChatQuestion

View File

@ -10,6 +10,7 @@ from langchain_core.pydantic_v1 import BaseModel as BaseModelV1
from langchain_core.pydantic_v1 import Field as FieldV1
from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAI
from quivr_api.logger import get_logger
from quivr_api.modules.brain.knowledge_brain_qa import KnowledgeBrainQA
@ -113,7 +114,6 @@ class MultiContractBrain(KnowledgeBrainQA):
)
def get_chain(self):
list_files_array = (
self.knowledge_qa.knowledge_service.get_all_knowledge_in_brain(
self.brain_id
@ -176,7 +176,6 @@ class MultiContractBrain(KnowledgeBrainQA):
api_base=api_base,
) # pyright: ignore reportPrivateUsage=none
if self.model_compatible_with_function_calling(self.model):
# And finally, we do the part that returns the answers
llm_function = ChatOpenAI(
max_tokens=self.max_tokens,

View File

@ -7,6 +7,7 @@ from typing import Any, List, Optional
import requests
from fastapi import UploadFile
from pydantic import BaseModel
from quivr_api.celery_config import celery
from quivr_api.logger import get_logger
from quivr_api.modules.brain.entity.integration_brain import IntegrationEntity
@ -384,7 +385,6 @@ class NotionConnector(IntegrationBrain, Integration):
if __name__ == "__main__":
notion = NotionConnector(
brain_id="73f7d092-d596-4fd0-b24f-24031e9b53cd",
user_id="39418e3b-0258-4452-af60-7acfcc1263ff",

View File

@ -4,6 +4,7 @@ from uuid import UUID
from langchain_community.chat_models import ChatLiteLLM
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from quivr_api.logger import get_logger
from quivr_api.modules.brain.knowledge_brain_qa import KnowledgeBrainQA
from quivr_api.modules.chat.dto.chats import ChatQuestion

View File

@ -7,6 +7,7 @@ from langchain_community.utilities import SQLDatabase
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from quivr_api.modules.brain.integrations.SQL.SQL_connector import SQLConnector
from quivr_api.modules.brain.knowledge_brain_qa import KnowledgeBrainQA
from quivr_api.modules.brain.repository.integration_brains import IntegrationBrain
@ -85,7 +86,6 @@ class SQLBrain(KnowledgeBrainQA, IntegrationBrain):
async def generate_stream(
self, chat_id: UUID, question: ChatQuestion, save_answer: bool = True
) -> AsyncIterable:
conversational_qa_chain = self.get_chain()
transformed_history, streamed_chat_history = (
self.initialize_streamed_chat_history(chat_id, question)

View File

@ -12,13 +12,14 @@ from langchain_core.pydantic_v1 import BaseModel as BaseModelV1
from langchain_core.pydantic_v1 import Field as FieldV1
from langchain_openai import ChatOpenAI
from langgraph.graph import END, StateGraph
from typing_extensions import TypedDict
from quivr_api.logger import get_logger
from quivr_api.modules.brain.knowledge_brain_qa import KnowledgeBrainQA
from quivr_api.modules.chat.dto.chats import ChatQuestion
from quivr_api.modules.chat.dto.outputs import GetChatHistoryOutput
from quivr_api.modules.chat.service.chat_service import ChatService
from quivr_api.modules.dependencies import get_service
from typing_extensions import TypedDict
# Post-processing
@ -107,7 +108,7 @@ class SelfBrain(KnowledgeBrainQA):
structured_llm_grader = llm.with_structured_output(GradeDocuments)
# Prompt
system = """You are a grader assessing relevance of a retrieved document to a user question. \n
system = """You are a grader assessing relevance of a retrieved document to a user question. \n
It does not need to be a stringent test. The goal is to filter out erroneous retrievals. \n
If the document contains keyword(s) or semantic meaning related to the user question, grade it as relevant. \n
Give a binary score 'yes' or 'no' score to indicate whether the document is relevant to the question."""
@ -129,9 +130,9 @@ class SelfBrain(KnowledgeBrainQA):
# Prompt
human_prompt = """You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.
Question: {question}
Question: {question}
Context: {context}
Context: {context}
Answer:
"""
@ -150,7 +151,7 @@ class SelfBrain(KnowledgeBrainQA):
structured_llm_grader = llm.with_structured_output(GradeHallucinations)
# Prompt
system = """You are a grader assessing whether an LLM generation is grounded in / supported by a set of retrieved facts. \n
system = """You are a grader assessing whether an LLM generation is grounded in / supported by a set of retrieved facts. \n
Give a binary score 'yes' or 'no'. 'Yes' means that the answer is grounded in / supported by the set of facts."""
hallucination_prompt = ChatPromptTemplate.from_messages(
[
@ -172,7 +173,7 @@ class SelfBrain(KnowledgeBrainQA):
structured_llm_grader = llm.with_structured_output(GradeAnswer)
# Prompt
system = """You are a grader assessing whether an answer addresses / resolves a question \n
system = """You are a grader assessing whether an answer addresses / resolves a question \n
Give a binary score 'yes' or 'no'. Yes' means that the answer resolves the question."""
answer_prompt = ChatPromptTemplate.from_messages(
[
@ -193,7 +194,7 @@ class SelfBrain(KnowledgeBrainQA):
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# Prompt
system = """You a question re-writer that converts an input question to a better version that is optimized \n
system = """You a question re-writer that converts an input question to a better version that is optimized \n
for vectorstore retrieval. Look at the input and try to reason about the underlying semantic intent / meaning."""
re_write_prompt = ChatPromptTemplate.from_messages(
[
@ -210,13 +211,11 @@ class SelfBrain(KnowledgeBrainQA):
return question_rewriter
def get_chain(self):
graph = self.create_graph()
return graph
def create_graph(self):
workflow = StateGraph(GraphState)
# Define the nodes

View File

@ -18,6 +18,8 @@ from langchain_core.runnables import RunnableLambda, RunnablePassthrough
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, ConfigDict
from pydantic_settings import BaseSettings
from supabase.client import Client
from quivr_api.logger import get_logger
# Importing settings related to the 'brain'
@ -33,7 +35,6 @@ from quivr_api.modules.dependencies import get_service
from quivr_api.modules.knowledge.repository.knowledges import KnowledgeRepository
from quivr_api.modules.prompt.service.get_prompt_to_use import get_prompt_to_use
from quivr_api.vectorstore.supabase import CustomSupabaseVectorStore
from supabase.client import Client
logger = get_logger(__name__)

View File

@ -1,5 +1,7 @@
from uuid import UUID
from sqlalchemy import text
from quivr_api.logger import get_logger
from quivr_api.models.settings import (
get_embedding_client,
@ -11,7 +13,6 @@ from quivr_api.modules.brain.entity.brain_entity import BrainEntity
from quivr_api.modules.brain.repository.interfaces.brains_interface import (
BrainsInterface,
)
from sqlalchemy import text
logger = get_logger(__name__)

View File

@ -13,7 +13,6 @@ from quivr_api.modules.brain.repository.interfaces.integration_brains_interface
class Integration(ABC):
@abstractmethod
def load(self):
pass
@ -63,7 +62,6 @@ class IntegrationBrain(IntegrationBrainInterface):
return IntegrationEntity(**response.data[0])
def add_integration_brain(self, brain_id, user_id, integration_id, settings):
response = (
self.db.table("integrations_user")
.insert(
@ -116,7 +114,6 @@ class IntegrationBrain(IntegrationBrainInterface):
class IntegrationDescription(IntegrationDescriptionInterface):
def __init__(self):
self.db = get_supabase_client()

View File

@ -2,5 +2,7 @@
from .brains_interface import BrainsInterface
from .brains_users_interface import BrainsUsersInterface
from .brains_vectors_interface import BrainsVectorsInterface
from .integration_brains_interface import (IntegrationBrainInterface,
IntegrationDescriptionInterface)
from .integration_brains_interface import (
IntegrationBrainInterface,
IntegrationDescriptionInterface,
)

View File

@ -38,7 +38,6 @@ class IntegrationBrainInterface(ABC):
class IntegrationDescriptionInterface(ABC):
@abstractmethod
def get_integration_description(
self, integration_id: UUID

View File

@ -2,6 +2,7 @@ from typing import List, Optional, Union
from uuid import UUID
from fastapi import Depends, HTTPException, status
from quivr_api.middlewares.auth.auth_bearer import get_current_user
from quivr_api.modules.brain.entity.brain_entity import RoleEnum
from quivr_api.modules.brain.service.brain_service import BrainService
@ -13,7 +14,7 @@ brain_service = BrainService()
def has_brain_authorization(
required_roles: Optional[Union[RoleEnum, List[RoleEnum]]] = RoleEnum.Owner
required_roles: Optional[Union[RoleEnum, List[RoleEnum]]] = RoleEnum.Owner,
):
"""
Decorator to check if the user has the required role(s) for the brain

View File

@ -2,6 +2,7 @@ from typing import Optional
from uuid import UUID
from fastapi import HTTPException
from quivr_api.celery_config import celery
from quivr_api.logger import get_logger
from quivr_api.modules.brain.dto.inputs import (

View File

@ -2,6 +2,7 @@ from typing import List
from uuid import UUID
from fastapi import HTTPException
from quivr_api.logger import get_logger
from quivr_api.modules.brain.entity.brain_entity import (
BrainEntity,

View File

@ -1,6 +1,7 @@
from uuid import UUID
from attr import dataclass
from quivr_api.logger import get_logger
from quivr_api.models.settings import get_embedding_client, get_supabase_client
from quivr_api.modules.upload.service.generate_file_signed_url import (

View File

@ -1,6 +1,7 @@
from typing import List, Tuple
from langchain_core.messages import AIMessage, BaseMessage, HumanMessage, SystemMessage
from quivr_api.modules.chat.dto.outputs import GetChatHistoryOutput

View File

@ -15,5 +15,7 @@ def get_prompt_to_use_id(
return (
prompt_id
if prompt_id
else brain_service.get_brain_prompt_id(brain_id) if brain_id else None
else brain_service.get_brain_prompt_id(brain_id)
if brain_id
else None
)

View File

@ -1,2 +0,0 @@
from fastapi import HTTPException
from quivr_api.modules.brain.dto.inputs import CreateBrainProperties

View File

@ -2,6 +2,7 @@ import time
from uuid import UUID
from fastapi import HTTPException
from quivr_api.logger import get_logger
from quivr_api.models.databases.llm_models import LLMModel
from quivr_api.modules.user.service.user_usage import UserUsage

View File

@ -3,6 +3,7 @@ from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, Request
from fastapi.responses import StreamingResponse
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.brain.entity.brain_entity import RoleEnum

View File

@ -3,6 +3,7 @@ from typing import List, Optional, Tuple, Union
from uuid import UUID
from pydantic import BaseModel
from quivr_api.modules.chat.dto.outputs import GetChatHistoryOutput
from quivr_api.modules.notification.entity.notification import Notification

View File

@ -2,12 +2,12 @@ from datetime import datetime
from typing import List
from uuid import UUID
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlmodel import JSON, TIMESTAMP, Column, Field, Relationship, SQLModel, text
from sqlmodel import UUID as PGUUID
from quivr_api.modules.brain.entity.brain_entity import Brain
from quivr_api.modules.user.entity.user_identity import User
from sqlalchemy.ext.asyncio import AsyncAttrs
from sqlmodel import JSON, TIMESTAMP
from sqlmodel import UUID as PGUUID
from sqlmodel import Column, Field, Relationship, SQLModel, text
class Chat(SQLModel, table=True):

View File

@ -1,13 +1,14 @@
from typing import Sequence
from uuid import UUID
from sqlalchemy import exc
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
from quivr_api.models.settings import get_supabase_client
from quivr_api.modules.chat.dto.inputs import ChatMessageProperties, QuestionAndAnswer
from quivr_api.modules.chat.entity.chat import Chat, ChatHistory
from quivr_api.modules.dependencies import BaseRepository
from sqlalchemy import exc
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
class ChatRepository(BaseRepository):
@ -40,7 +41,8 @@ class ChatRepository(BaseRepository):
async def get_chat_history(self, chat_id: UUID) -> Sequence[ChatHistory]:
query = (
select(ChatHistory).where(ChatHistory.chat_id == chat_id)
select(ChatHistory)
.where(ChatHistory.chat_id == chat_id)
# TODO: type hints of sqlmodel arent stable for order_by
.order_by(ChatHistory.message_time) # type: ignore
)

View File

@ -1 +1 @@
from .knowledge_routes import knowledge_router
from .knowledge_routes import knowledge_router

View File

@ -1,6 +1,7 @@
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.brain.entity.brain_entity import RoleEnum

View File

@ -2,12 +2,13 @@ from abc import ABC, abstractmethod
from typing import List
from uuid import UUID
from quivr_core.models import QuivrKnowledge as Knowledge
from quivr_api.modules.knowledge.dto.inputs import (
CreateKnowledgeProperties,
KnowledgeStatus,
)
from quivr_api.modules.knowledge.dto.outputs import DeleteKnowledgeResponse
from quivr_core.models import QuivrKnowledge as Knowledge
class KnowledgeInterface(ABC):

View File

@ -1,13 +1,14 @@
from uuid import UUID
from fastapi import HTTPException
from quivr_core.models import QuivrKnowledge as Knowledge
from quivr_api.models.settings import get_supabase_client
from quivr_api.modules.knowledge.dto.inputs import KnowledgeStatus
from quivr_api.modules.knowledge.dto.outputs import DeleteKnowledgeResponse
from quivr_api.modules.knowledge.repository.knowledge_interface import (
KnowledgeInterface,
)
from quivr_core.models import QuivrKnowledge as Knowledge
class KnowledgeRepository(KnowledgeInterface):

View File

@ -1,5 +1,7 @@
from uuid import UUID
from quivr_core.models import QuivrKnowledge as Knowledge
from quivr_api.logger import get_logger
from quivr_api.modules.knowledge.dto.inputs import (
CreateKnowledgeProperties,
@ -9,7 +11,6 @@ from quivr_api.modules.knowledge.repository.knowledge_interface import (
KnowledgeInterface,
)
from quivr_api.modules.knowledge.repository.knowledges import KnowledgeRepository
from quivr_core.models import QuivrKnowledge as Knowledge
logger = get_logger(__name__)

View File

@ -1,6 +1,7 @@
from typing import Annotated, List
from fastapi import APIRouter, Depends
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.dependencies import get_service

View File

@ -1,10 +1,11 @@
from typing import Sequence
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
from quivr_api.models.settings import get_supabase_client
from quivr_api.modules.dependencies import BaseRepository
from quivr_api.modules.models.entity.model import Model
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
class ModelRepository(BaseRepository):

View File

@ -1,5 +1,6 @@
import pytest
import pytest_asyncio
from quivr_api.modules.models.entity.model import Model

View File

@ -1 +1 @@
from .inputs import NotificationUpdatableProperties
from .inputs import NotificationUpdatableProperties

View File

@ -3,6 +3,7 @@ from uuid import UUID
from venv import logger
from pydantic import BaseModel
from quivr_api.logger import get_logger
from quivr_api.modules.notification.entity.notification import NotificationsStatusEnum

View File

@ -1,4 +1,5 @@
from fastapi import APIRouter, Depends
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.user.entity.user_identity import UserIdentity

View File

@ -1,6 +1,7 @@
from uuid import UUID
from fastapi import APIRouter, Depends
from quivr_api.middlewares.auth import AuthBearer
from quivr_api.modules.prompt.entity.prompt import (
CreatePromptProperties,

View File

@ -1 +1,7 @@
from .prompt import Prompt, PromptStatusEnum, CreatePromptProperties, PromptUpdatableProperties, DeletePromptResponse
from .prompt import (
CreatePromptProperties,
DeletePromptResponse,
Prompt,
PromptStatusEnum,
PromptUpdatableProperties,
)

View File

@ -1,4 +1,5 @@
from fastapi import HTTPException
from quivr_api.models.settings import get_supabase_client
from quivr_api.modules.prompt.entity.prompt import Prompt
from quivr_api.modules.prompt.repository.prompts_interface import (

View File

@ -1,31 +1,38 @@
import datetime
from uuid import UUID, uuid4
from quivr_api.logger import get_logger
from quivr_api.models.settings import (get_embedding_client,
get_supabase_client, settings)
from quivr_api.modules.brain.entity.brain_entity import BrainEntity
from quivr_api.modules.brain.service.brain_service import BrainService
from quivr_api.modules.brain.service.utils.format_chat_history import \
format_chat_history
from quivr_api.modules.chat.controller.chat.utils import (
compute_cost, find_model_and_generate_metadata, update_user_usage)
from quivr_api.modules.chat.dto.inputs import CreateChatHistory
from quivr_api.modules.chat.dto.outputs import GetChatHistoryOutput
from quivr_api.modules.chat.service.chat_service import ChatService
from quivr_api.modules.knowledge.repository.knowledges import \
KnowledgeRepository
from quivr_api.modules.prompt.entity.prompt import Prompt
from quivr_api.modules.prompt.service.prompt_service import PromptService
from quivr_api.modules.user.entity.user_identity import UserIdentity
from quivr_api.modules.user.service.user_usage import UserUsage
from quivr_api.vectorstore.supabase import CustomSupabaseVectorStore
from quivr_core.chat import ChatHistory as ChatHistoryCore
from quivr_core.config import LLMEndpointConfig, RAGConfig
from quivr_core.llm.llm_endpoint import LLMEndpoint
from quivr_core.models import ParsedRAGResponse, RAGResponseMetadata
from quivr_core.quivr_rag import QuivrQARAG
from quivr_api.logger import get_logger
from quivr_api.models.settings import (
get_embedding_client,
get_supabase_client,
settings,
)
from quivr_api.modules.brain.entity.brain_entity import BrainEntity
from quivr_api.modules.brain.service.brain_service import BrainService
from quivr_api.modules.brain.service.utils.format_chat_history import (
format_chat_history,
)
from quivr_api.modules.chat.controller.chat.utils import (
compute_cost,
find_model_and_generate_metadata,
update_user_usage,
)
from quivr_api.modules.chat.dto.inputs import CreateChatHistory
from quivr_api.modules.chat.dto.outputs import GetChatHistoryOutput
from quivr_api.modules.chat.service.chat_service import ChatService
from quivr_api.modules.knowledge.repository.knowledges import KnowledgeRepository
from quivr_api.modules.prompt.entity.prompt import Prompt
from quivr_api.modules.prompt.service.prompt_service import PromptService
from quivr_api.modules.user.entity.user_identity import UserIdentity
from quivr_api.modules.user.service.user_usage import UserUsage
from quivr_api.vectorstore.supabase import CustomSupabaseVectorStore
from .utils import generate_source
logger = get_logger(__name__)

View File

@ -4,6 +4,7 @@ import requests
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse
from msal import ConfidentialClientApplication
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.sync.dto.inputs import SyncsUserInput, SyncUserUpdateInput

View File

@ -3,6 +3,7 @@ import os
from dropbox import Dropbox, DropboxOAuth2Flow
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.sync.dto.inputs import SyncsUserInput, SyncUserUpdateInput

View File

@ -3,6 +3,7 @@ import os
import requests
from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.sync.dto.inputs import SyncsUserInput, SyncUserUpdateInput

View File

@ -5,6 +5,7 @@ from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi.responses import HTMLResponse
from google_auth_oauthlib.flow import Flow
from googleapiclient.discovery import build
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.sync.dto.inputs import SyncsUserInput, SyncUserUpdateInput

View File

@ -50,4 +50,4 @@ successfullConnectionPage = """
</div>
</body>
</html>
"""
"""

View File

@ -3,6 +3,7 @@ from typing import Optional
from uuid import UUID
from fastapi import HTTPException, UploadFile
from quivr_api.celery_worker import process_file_and_notify
from quivr_api.logger import get_logger
from quivr_api.modules.brain.entity.brain_entity import RoleEnum
@ -74,13 +75,13 @@ async def upload_file(
status_code=403,
detail=f"File {upload_file.filename} already exists in storage.",
)
else:
notification_service.update_notification_by_id(
notification_id,
NotificationUpdatableProperties(
status=NotificationsStatusEnum.ERROR,
description=f"There was an error uploading the file",
description="There was an error uploading the file",
),
)
raise HTTPException(

View File

@ -1,4 +1,4 @@
from .email_sender import EmailSenderTool
from .image_generator import ImageGeneratorTool
from .web_search import WebSearchTool
from .url_reader import URLReaderTool
from .email_sender import EmailSenderTool
from .web_search import WebSearchTool

View File

@ -10,6 +10,7 @@ from langchain.pydantic_v1 import Field as FieldV1
from langchain_community.document_loaders import PlaywrightURLLoader
from langchain_core.tools import BaseTool
from pydantic import BaseModel
from quivr_api.logger import get_logger
from quivr_api.models.settings import BrainSettings, SendEmailSettings
from quivr_api.packages.emails.send_email import send_email

View File

@ -11,6 +11,7 @@ from langchain.pydantic_v1 import Field as FieldV1
from langchain_community.document_loaders import PlaywrightURLLoader
from langchain_core.tools import BaseTool
from pydantic import BaseModel
from quivr_api.logger import get_logger
logger = get_logger(__name__)
@ -29,7 +30,6 @@ class URLReaderTool(BaseTool):
def _run(
self, url: str, run_manager: Optional[CallbackManagerForToolRun] = None
) -> Dict:
loader = PlaywrightURLLoader(urls=[url], remove_selectors=["header", "footer"])
data = loader.load()

View File

@ -10,6 +10,7 @@ from langchain.pydantic_v1 import BaseModel as BaseModelV1
from langchain.pydantic_v1 import Field as FieldV1
from langchain_core.tools import BaseTool
from pydantic import BaseModel
from quivr_api.logger import get_logger
logger = get_logger(__name__)

View File

@ -3,6 +3,7 @@ from typing import Optional
from uuid import UUID
from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile
from quivr_api.celery_worker import process_file_and_notify
from quivr_api.logger import get_logger
from quivr_api.middlewares.auth import AuthBearer, get_current_user
@ -82,7 +83,6 @@ async def upload_file(
except Exception as e:
print(e)
if "The resource already exists" in str(e):
notification_service.update_notification_by_id(
upload_notification.id if upload_notification else None,
@ -100,7 +100,7 @@ async def upload_file(
upload_notification.id if upload_notification else None,
NotificationUpdatableProperties(
status=NotificationsStatusEnum.ERROR,
description=f"There was an error uploading the file",
description="There was an error uploading the file",
),
)
raise HTTPException(

View File

@ -1,8 +1,9 @@
from multiprocessing import get_logger
from quivr_api.models.settings import get_supabase_client
from supabase.client import Client
from quivr_api.models.settings import get_supabase_client
logger = get_logger()
SIGNED_URL_EXPIRATION_PERIOD_IN_SECONDS = 3600

View File

@ -1,8 +1,9 @@
from multiprocessing import get_logger
from quivr_api.models.settings import get_supabase_client
from supabase.client import Client
from quivr_api.models.settings import get_supabase_client
logger = get_logger()

View File

@ -4,9 +4,10 @@ from multiprocessing import get_logger
from langchain.pydantic_v1 import Field
from langchain.schema import Document
from supabase.client import Client
from quivr_api.logger import get_logger
from quivr_api.models.settings import get_supabase_client
from supabase.client import Client
logger = get_logger(__name__)

View File

@ -1 +1 @@
this is a test
this is a test

View File

@ -1,4 +1,5 @@
from fastapi import APIRouter, Depends, Request
from quivr_api.middlewares.auth import AuthBearer, get_current_user
from quivr_api.modules.brain.service.brain_user_service import BrainUserService
from quivr_api.modules.user.dto.inputs import UserUpdatableProperties

View File

@ -10,4 +10,3 @@ class UserUpdatableProperties(BaseModel):
onboarded: Optional[bool] = None
company_size: Optional[str] = None
usage_purpose: Optional[str] = None

View File

@ -1 +1 @@
from .user_service import UserService
from .user_service import UserService

View File

@ -1,6 +1,7 @@
from typing import Dict
import resend
from quivr_api.models.settings import ResendSettings

Some files were not shown because too many files have changed in this diff Show More