mirror of
https://github.com/open-webui/open-webui
synced 2025-05-29 09:42:12 +00:00
enh: bypass embedding and retrieval
This commit is contained in:
parent
1c2e36f1b7
commit
57010901e6
@ -1502,13 +1502,16 @@ VECTOR_DB = os.environ.get("VECTOR_DB", "chroma")
|
|||||||
# Chroma
|
# Chroma
|
||||||
if VECTOR_DB == "chroma":
|
if VECTOR_DB == "chroma":
|
||||||
import chromadb
|
import chromadb
|
||||||
|
|
||||||
CHROMA_DATA_PATH = f"{DATA_DIR}/vector_db"
|
CHROMA_DATA_PATH = f"{DATA_DIR}/vector_db"
|
||||||
CHROMA_TENANT = os.environ.get("CHROMA_TENANT", chromadb.DEFAULT_TENANT)
|
CHROMA_TENANT = os.environ.get("CHROMA_TENANT", chromadb.DEFAULT_TENANT)
|
||||||
CHROMA_DATABASE = os.environ.get("CHROMA_DATABASE", chromadb.DEFAULT_DATABASE)
|
CHROMA_DATABASE = os.environ.get("CHROMA_DATABASE", chromadb.DEFAULT_DATABASE)
|
||||||
CHROMA_HTTP_HOST = os.environ.get("CHROMA_HTTP_HOST", "")
|
CHROMA_HTTP_HOST = os.environ.get("CHROMA_HTTP_HOST", "")
|
||||||
CHROMA_HTTP_PORT = int(os.environ.get("CHROMA_HTTP_PORT", "8000"))
|
CHROMA_HTTP_PORT = int(os.environ.get("CHROMA_HTTP_PORT", "8000"))
|
||||||
CHROMA_CLIENT_AUTH_PROVIDER = os.environ.get("CHROMA_CLIENT_AUTH_PROVIDER", "")
|
CHROMA_CLIENT_AUTH_PROVIDER = os.environ.get("CHROMA_CLIENT_AUTH_PROVIDER", "")
|
||||||
CHROMA_CLIENT_AUTH_CREDENTIALS = os.environ.get("CHROMA_CLIENT_AUTH_CREDENTIALS", "")
|
CHROMA_CLIENT_AUTH_CREDENTIALS = os.environ.get(
|
||||||
|
"CHROMA_CLIENT_AUTH_CREDENTIALS", ""
|
||||||
|
)
|
||||||
# Comma-separated list of header=value pairs
|
# Comma-separated list of header=value pairs
|
||||||
CHROMA_HTTP_HEADERS = os.environ.get("CHROMA_HTTP_HEADERS", "")
|
CHROMA_HTTP_HEADERS = os.environ.get("CHROMA_HTTP_HEADERS", "")
|
||||||
if CHROMA_HTTP_HEADERS:
|
if CHROMA_HTTP_HEADERS:
|
||||||
@ -1608,6 +1611,14 @@ DOCUMENT_INTELLIGENCE_KEY = PersistentConfig(
|
|||||||
os.getenv("DOCUMENT_INTELLIGENCE_KEY", ""),
|
os.getenv("DOCUMENT_INTELLIGENCE_KEY", ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
BYPASS_EMBEDDING_AND_RETRIEVAL = PersistentConfig(
|
||||||
|
"BYPASS_EMBEDDING_AND_RETRIEVAL",
|
||||||
|
"rag.bypass_embedding_and_retrieval",
|
||||||
|
os.environ.get("BYPASS_EMBEDDING_AND_RETRIEVAL", "False").lower() == "true",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
RAG_TOP_K = PersistentConfig(
|
RAG_TOP_K = PersistentConfig(
|
||||||
"RAG_TOP_K", "rag.top_k", int(os.environ.get("RAG_TOP_K", "3"))
|
"RAG_TOP_K", "rag.top_k", int(os.environ.get("RAG_TOP_K", "3"))
|
||||||
)
|
)
|
||||||
@ -1824,10 +1835,10 @@ RAG_WEB_SEARCH_ENGINE = PersistentConfig(
|
|||||||
os.getenv("RAG_WEB_SEARCH_ENGINE", ""),
|
os.getenv("RAG_WEB_SEARCH_ENGINE", ""),
|
||||||
)
|
)
|
||||||
|
|
||||||
RAG_WEB_SEARCH_FULL_CONTEXT = PersistentConfig(
|
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = PersistentConfig(
|
||||||
"RAG_WEB_SEARCH_FULL_CONTEXT",
|
"BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL",
|
||||||
"rag.web.search.full_context",
|
"rag.web.search.bypass_embedding_and_retrieval",
|
||||||
os.getenv("RAG_WEB_SEARCH_FULL_CONTEXT", "False").lower() == "true",
|
os.getenv("BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL", "False").lower() == "true",
|
||||||
)
|
)
|
||||||
|
|
||||||
# You can provide a list of your own websites to filter after performing a web search.
|
# You can provide a list of your own websites to filter after performing a web search.
|
||||||
|
@ -162,6 +162,7 @@ from open_webui.config import (
|
|||||||
RAG_TEMPLATE,
|
RAG_TEMPLATE,
|
||||||
DEFAULT_RAG_TEMPLATE,
|
DEFAULT_RAG_TEMPLATE,
|
||||||
RAG_FULL_CONTEXT,
|
RAG_FULL_CONTEXT,
|
||||||
|
BYPASS_EMBEDDING_AND_RETRIEVAL,
|
||||||
RAG_EMBEDDING_MODEL,
|
RAG_EMBEDDING_MODEL,
|
||||||
RAG_EMBEDDING_MODEL_AUTO_UPDATE,
|
RAG_EMBEDDING_MODEL_AUTO_UPDATE,
|
||||||
RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE,
|
RAG_EMBEDDING_MODEL_TRUST_REMOTE_CODE,
|
||||||
@ -191,7 +192,7 @@ from open_webui.config import (
|
|||||||
YOUTUBE_LOADER_PROXY_URL,
|
YOUTUBE_LOADER_PROXY_URL,
|
||||||
# Retrieval (Web Search)
|
# Retrieval (Web Search)
|
||||||
RAG_WEB_SEARCH_ENGINE,
|
RAG_WEB_SEARCH_ENGINE,
|
||||||
RAG_WEB_SEARCH_FULL_CONTEXT,
|
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL,
|
||||||
RAG_WEB_SEARCH_RESULT_COUNT,
|
RAG_WEB_SEARCH_RESULT_COUNT,
|
||||||
RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
|
RAG_WEB_SEARCH_CONCURRENT_REQUESTS,
|
||||||
RAG_WEB_SEARCH_TRUST_ENV,
|
RAG_WEB_SEARCH_TRUST_ENV,
|
||||||
@ -531,6 +532,7 @@ app.state.config.FILE_MAX_COUNT = RAG_FILE_MAX_COUNT
|
|||||||
|
|
||||||
|
|
||||||
app.state.config.RAG_FULL_CONTEXT = RAG_FULL_CONTEXT
|
app.state.config.RAG_FULL_CONTEXT = RAG_FULL_CONTEXT
|
||||||
|
app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL = BYPASS_EMBEDDING_AND_RETRIEVAL
|
||||||
app.state.config.ENABLE_RAG_HYBRID_SEARCH = ENABLE_RAG_HYBRID_SEARCH
|
app.state.config.ENABLE_RAG_HYBRID_SEARCH = ENABLE_RAG_HYBRID_SEARCH
|
||||||
app.state.config.ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION = (
|
app.state.config.ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION = (
|
||||||
ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION
|
ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION
|
||||||
@ -567,7 +569,9 @@ app.state.config.YOUTUBE_LOADER_PROXY_URL = YOUTUBE_LOADER_PROXY_URL
|
|||||||
|
|
||||||
app.state.config.ENABLE_RAG_WEB_SEARCH = ENABLE_RAG_WEB_SEARCH
|
app.state.config.ENABLE_RAG_WEB_SEARCH = ENABLE_RAG_WEB_SEARCH
|
||||||
app.state.config.RAG_WEB_SEARCH_ENGINE = RAG_WEB_SEARCH_ENGINE
|
app.state.config.RAG_WEB_SEARCH_ENGINE = RAG_WEB_SEARCH_ENGINE
|
||||||
app.state.config.RAG_WEB_SEARCH_FULL_CONTEXT = RAG_WEB_SEARCH_FULL_CONTEXT
|
app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = (
|
||||||
|
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL
|
||||||
|
)
|
||||||
app.state.config.RAG_WEB_SEARCH_DOMAIN_FILTER_LIST = RAG_WEB_SEARCH_DOMAIN_FILTER_LIST
|
app.state.config.RAG_WEB_SEARCH_DOMAIN_FILTER_LIST = RAG_WEB_SEARCH_DOMAIN_FILTER_LIST
|
||||||
|
|
||||||
app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ENABLE_GOOGLE_DRIVE_INTEGRATION
|
app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = ENABLE_GOOGLE_DRIVE_INTEGRATION
|
||||||
|
@ -17,6 +17,7 @@ from open_webui.retrieval.vector.connector import VECTOR_DB_CLIENT
|
|||||||
from open_webui.utils.misc import get_last_user_message, calculate_sha256_string
|
from open_webui.utils.misc import get_last_user_message, calculate_sha256_string
|
||||||
|
|
||||||
from open_webui.models.users import UserModel
|
from open_webui.models.users import UserModel
|
||||||
|
from open_webui.models.files import Files
|
||||||
|
|
||||||
from open_webui.env import (
|
from open_webui.env import (
|
||||||
SRC_LOG_LEVELS,
|
SRC_LOG_LEVELS,
|
||||||
@ -342,6 +343,7 @@ def get_embedding_function(
|
|||||||
|
|
||||||
|
|
||||||
def get_sources_from_files(
|
def get_sources_from_files(
|
||||||
|
request,
|
||||||
files,
|
files,
|
||||||
queries,
|
queries,
|
||||||
embedding_function,
|
embedding_function,
|
||||||
@ -359,19 +361,64 @@ def get_sources_from_files(
|
|||||||
relevant_contexts = []
|
relevant_contexts = []
|
||||||
|
|
||||||
for file in files:
|
for file in files:
|
||||||
|
|
||||||
|
context = None
|
||||||
if file.get("docs"):
|
if file.get("docs"):
|
||||||
|
# BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL
|
||||||
context = {
|
context = {
|
||||||
"documents": [[doc.get("content") for doc in file.get("docs")]],
|
"documents": [[doc.get("content") for doc in file.get("docs")]],
|
||||||
"metadatas": [[doc.get("metadata") for doc in file.get("docs")]],
|
"metadatas": [[doc.get("metadata") for doc in file.get("docs")]],
|
||||||
}
|
}
|
||||||
elif file.get("context") == "full":
|
elif file.get("context") == "full":
|
||||||
|
# Manual Full Mode Toggle
|
||||||
context = {
|
context = {
|
||||||
"documents": [[file.get("file").get("data", {}).get("content")]],
|
"documents": [[file.get("file").get("data", {}).get("content")]],
|
||||||
"metadatas": [[{"file_id": file.get("id"), "name": file.get("name")}]],
|
"metadatas": [[{"file_id": file.get("id"), "name": file.get("name")}]],
|
||||||
}
|
}
|
||||||
else:
|
elif (
|
||||||
context = None
|
file.get("type") != "web_search"
|
||||||
|
and request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL
|
||||||
|
):
|
||||||
|
# BYPASS_EMBEDDING_AND_RETRIEVAL
|
||||||
|
if file.get("type") == "collection":
|
||||||
|
file_ids = file.get("data", {}).get("file_ids", [])
|
||||||
|
|
||||||
|
documents = []
|
||||||
|
metadatas = []
|
||||||
|
for file_id in file_ids:
|
||||||
|
file_object = Files.get_file_by_id(file_id)
|
||||||
|
|
||||||
|
if file_object:
|
||||||
|
documents.append(file_object.data.get("content", ""))
|
||||||
|
metadatas.append(
|
||||||
|
{
|
||||||
|
"file_id": file_id,
|
||||||
|
"name": file_object.filename,
|
||||||
|
"source": file_object.filename,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"documents": [documents],
|
||||||
|
"metadatas": [metadatas],
|
||||||
|
}
|
||||||
|
|
||||||
|
elif file.get("id"):
|
||||||
|
file_object = Files.get_file_by_id(file.get("id"))
|
||||||
|
if file_object:
|
||||||
|
context = {
|
||||||
|
"documents": [[file_object.data.get("content", "")]],
|
||||||
|
"metadatas": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"file_id": file.get("id"),
|
||||||
|
"name": file_object.filename,
|
||||||
|
"source": file_object.filename,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
}
|
||||||
|
else:
|
||||||
collection_names = []
|
collection_names = []
|
||||||
if file.get("type") == "collection":
|
if file.get("type") == "collection":
|
||||||
if file.get("legacy"):
|
if file.get("legacy"):
|
||||||
@ -434,6 +481,7 @@ def get_sources_from_files(
|
|||||||
if context:
|
if context:
|
||||||
if "data" in file:
|
if "data" in file:
|
||||||
del file["data"]
|
del file["data"]
|
||||||
|
|
||||||
relevant_contexts.append({**context, "file": file})
|
relevant_contexts.append({**context, "file": file})
|
||||||
|
|
||||||
sources = []
|
sources = []
|
||||||
|
@ -107,8 +107,7 @@ class ChromaClient:
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except:
|
||||||
log.exception(f"{e}")
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def get(self, collection_name: str) -> Optional[GetResult]:
|
def get(self, collection_name: str) -> Optional[GetResult]:
|
||||||
|
@ -352,6 +352,7 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)):
|
|||||||
"status": True,
|
"status": True,
|
||||||
"pdf_extract_images": request.app.state.config.PDF_EXTRACT_IMAGES,
|
"pdf_extract_images": request.app.state.config.PDF_EXTRACT_IMAGES,
|
||||||
"RAG_FULL_CONTEXT": request.app.state.config.RAG_FULL_CONTEXT,
|
"RAG_FULL_CONTEXT": request.app.state.config.RAG_FULL_CONTEXT,
|
||||||
|
"BYPASS_EMBEDDING_AND_RETRIEVAL": request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL,
|
||||||
"enable_google_drive_integration": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
|
"enable_google_drive_integration": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
|
||||||
"enable_onedrive_integration": request.app.state.config.ENABLE_ONEDRIVE_INTEGRATION,
|
"enable_onedrive_integration": request.app.state.config.ENABLE_ONEDRIVE_INTEGRATION,
|
||||||
"content_extraction": {
|
"content_extraction": {
|
||||||
@ -378,7 +379,7 @@ async def get_rag_config(request: Request, user=Depends(get_admin_user)):
|
|||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION": request.app.state.config.ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION,
|
"ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION": request.app.state.config.ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION,
|
||||||
"RAG_WEB_SEARCH_FULL_CONTEXT": request.app.state.config.RAG_WEB_SEARCH_FULL_CONTEXT,
|
"BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL": request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL,
|
||||||
"search": {
|
"search": {
|
||||||
"enabled": request.app.state.config.ENABLE_RAG_WEB_SEARCH,
|
"enabled": request.app.state.config.ENABLE_RAG_WEB_SEARCH,
|
||||||
"drive": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
|
"drive": request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION,
|
||||||
@ -473,11 +474,12 @@ class WebSearchConfig(BaseModel):
|
|||||||
class WebConfig(BaseModel):
|
class WebConfig(BaseModel):
|
||||||
search: WebSearchConfig
|
search: WebSearchConfig
|
||||||
ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION: Optional[bool] = None
|
ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION: Optional[bool] = None
|
||||||
RAG_WEB_SEARCH_FULL_CONTEXT: Optional[bool] = None
|
BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL: Optional[bool] = None
|
||||||
|
|
||||||
|
|
||||||
class ConfigUpdateForm(BaseModel):
|
class ConfigUpdateForm(BaseModel):
|
||||||
RAG_FULL_CONTEXT: Optional[bool] = None
|
RAG_FULL_CONTEXT: Optional[bool] = None
|
||||||
|
BYPASS_EMBEDDING_AND_RETRIEVAL: Optional[bool] = None
|
||||||
pdf_extract_images: Optional[bool] = None
|
pdf_extract_images: Optional[bool] = None
|
||||||
enable_google_drive_integration: Optional[bool] = None
|
enable_google_drive_integration: Optional[bool] = None
|
||||||
enable_onedrive_integration: Optional[bool] = None
|
enable_onedrive_integration: Optional[bool] = None
|
||||||
@ -504,6 +506,12 @@ async def update_rag_config(
|
|||||||
else request.app.state.config.RAG_FULL_CONTEXT
|
else request.app.state.config.RAG_FULL_CONTEXT
|
||||||
)
|
)
|
||||||
|
|
||||||
|
request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL = (
|
||||||
|
form_data.BYPASS_EMBEDDING_AND_RETRIEVAL
|
||||||
|
if form_data.BYPASS_EMBEDDING_AND_RETRIEVAL is not None
|
||||||
|
else request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL
|
||||||
|
)
|
||||||
|
|
||||||
request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = (
|
request.app.state.config.ENABLE_GOOGLE_DRIVE_INTEGRATION = (
|
||||||
form_data.enable_google_drive_integration
|
form_data.enable_google_drive_integration
|
||||||
if form_data.enable_google_drive_integration is not None
|
if form_data.enable_google_drive_integration is not None
|
||||||
@ -557,8 +565,8 @@ async def update_rag_config(
|
|||||||
request.app.state.config.ENABLE_RAG_WEB_SEARCH = form_data.web.search.enabled
|
request.app.state.config.ENABLE_RAG_WEB_SEARCH = form_data.web.search.enabled
|
||||||
request.app.state.config.RAG_WEB_SEARCH_ENGINE = form_data.web.search.engine
|
request.app.state.config.RAG_WEB_SEARCH_ENGINE = form_data.web.search.engine
|
||||||
|
|
||||||
request.app.state.config.RAG_WEB_SEARCH_FULL_CONTEXT = (
|
request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL = (
|
||||||
form_data.web.RAG_WEB_SEARCH_FULL_CONTEXT
|
form_data.web.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL
|
||||||
)
|
)
|
||||||
|
|
||||||
request.app.state.config.SEARXNG_QUERY_URL = (
|
request.app.state.config.SEARXNG_QUERY_URL = (
|
||||||
@ -626,6 +634,7 @@ async def update_rag_config(
|
|||||||
"status": True,
|
"status": True,
|
||||||
"pdf_extract_images": request.app.state.config.PDF_EXTRACT_IMAGES,
|
"pdf_extract_images": request.app.state.config.PDF_EXTRACT_IMAGES,
|
||||||
"RAG_FULL_CONTEXT": request.app.state.config.RAG_FULL_CONTEXT,
|
"RAG_FULL_CONTEXT": request.app.state.config.RAG_FULL_CONTEXT,
|
||||||
|
"BYPASS_EMBEDDING_AND_RETRIEVAL": request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL,
|
||||||
"file": {
|
"file": {
|
||||||
"max_size": request.app.state.config.FILE_MAX_SIZE,
|
"max_size": request.app.state.config.FILE_MAX_SIZE,
|
||||||
"max_count": request.app.state.config.FILE_MAX_COUNT,
|
"max_count": request.app.state.config.FILE_MAX_COUNT,
|
||||||
@ -650,7 +659,7 @@ async def update_rag_config(
|
|||||||
},
|
},
|
||||||
"web": {
|
"web": {
|
||||||
"ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION": request.app.state.config.ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION,
|
"ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION": request.app.state.config.ENABLE_RAG_WEB_LOADER_SSL_VERIFICATION,
|
||||||
"RAG_WEB_SEARCH_FULL_CONTEXT": request.app.state.config.RAG_WEB_SEARCH_FULL_CONTEXT,
|
"BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL": request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL,
|
||||||
"search": {
|
"search": {
|
||||||
"enabled": request.app.state.config.ENABLE_RAG_WEB_SEARCH,
|
"enabled": request.app.state.config.ENABLE_RAG_WEB_SEARCH,
|
||||||
"engine": request.app.state.config.RAG_WEB_SEARCH_ENGINE,
|
"engine": request.app.state.config.RAG_WEB_SEARCH_ENGINE,
|
||||||
@ -1019,36 +1028,45 @@ def process_file(
|
|||||||
hash = calculate_sha256_string(text_content)
|
hash = calculate_sha256_string(text_content)
|
||||||
Files.update_file_hash_by_id(file.id, hash)
|
Files.update_file_hash_by_id(file.id, hash)
|
||||||
|
|
||||||
try:
|
if not request.app.state.config.BYPASS_EMBEDDING_AND_RETRIEVAL:
|
||||||
result = save_docs_to_vector_db(
|
try:
|
||||||
request,
|
result = save_docs_to_vector_db(
|
||||||
docs=docs,
|
request,
|
||||||
collection_name=collection_name,
|
docs=docs,
|
||||||
metadata={
|
collection_name=collection_name,
|
||||||
"file_id": file.id,
|
metadata={
|
||||||
"name": file.filename,
|
"file_id": file.id,
|
||||||
"hash": hash,
|
"name": file.filename,
|
||||||
},
|
"hash": hash,
|
||||||
add=(True if form_data.collection_name else False),
|
|
||||||
user=user,
|
|
||||||
)
|
|
||||||
|
|
||||||
if result:
|
|
||||||
Files.update_file_metadata_by_id(
|
|
||||||
file.id,
|
|
||||||
{
|
|
||||||
"collection_name": collection_name,
|
|
||||||
},
|
},
|
||||||
|
add=(True if form_data.collection_name else False),
|
||||||
|
user=user,
|
||||||
)
|
)
|
||||||
|
|
||||||
return {
|
if result:
|
||||||
"status": True,
|
Files.update_file_metadata_by_id(
|
||||||
"collection_name": collection_name,
|
file.id,
|
||||||
"filename": file.filename,
|
{
|
||||||
"content": text_content,
|
"collection_name": collection_name,
|
||||||
}
|
},
|
||||||
except Exception as e:
|
)
|
||||||
raise e
|
|
||||||
|
return {
|
||||||
|
"status": True,
|
||||||
|
"collection_name": collection_name,
|
||||||
|
"filename": file.filename,
|
||||||
|
"content": text_content,
|
||||||
|
}
|
||||||
|
except Exception as e:
|
||||||
|
raise e
|
||||||
|
else:
|
||||||
|
return {
|
||||||
|
"status": True,
|
||||||
|
"collection_name": None,
|
||||||
|
"filename": file.filename,
|
||||||
|
"content": text_content,
|
||||||
|
}
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
if "No pandoc was found" in str(e):
|
if "No pandoc was found" in str(e):
|
||||||
@ -1408,9 +1426,11 @@ async def process_web_search(
|
|||||||
)
|
)
|
||||||
docs = await loader.aload()
|
docs = await loader.aload()
|
||||||
|
|
||||||
if request.app.state.config.RAG_WEB_SEARCH_FULL_CONTEXT:
|
if request.app.state.config.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL:
|
||||||
return {
|
return {
|
||||||
"status": True,
|
"status": True,
|
||||||
|
"collection_name": None,
|
||||||
|
"filenames": urls,
|
||||||
"docs": [
|
"docs": [
|
||||||
{
|
{
|
||||||
"content": doc.page_content,
|
"content": doc.page_content,
|
||||||
@ -1418,7 +1438,6 @@ async def process_web_search(
|
|||||||
}
|
}
|
||||||
for doc in docs
|
for doc in docs
|
||||||
],
|
],
|
||||||
"filenames": urls,
|
|
||||||
"loaded_count": len(docs),
|
"loaded_count": len(docs),
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
|
@ -351,24 +351,25 @@ async def chat_web_search_handler(
|
|||||||
all_results.append(results)
|
all_results.append(results)
|
||||||
files = form_data.get("files", [])
|
files = form_data.get("files", [])
|
||||||
|
|
||||||
if request.app.state.config.RAG_WEB_SEARCH_FULL_CONTEXT:
|
if results.get("collection_name"):
|
||||||
files.append(
|
|
||||||
{
|
|
||||||
"docs": results.get("docs", []),
|
|
||||||
"name": searchQuery,
|
|
||||||
"type": "web_search_docs",
|
|
||||||
"urls": results["filenames"],
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
files.append(
|
files.append(
|
||||||
{
|
{
|
||||||
"collection_name": results["collection_name"],
|
"collection_name": results["collection_name"],
|
||||||
"name": searchQuery,
|
"name": searchQuery,
|
||||||
"type": "web_search_results",
|
"type": "web_search",
|
||||||
"urls": results["filenames"],
|
"urls": results["filenames"],
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
elif results.get("docs"):
|
||||||
|
files.append(
|
||||||
|
{
|
||||||
|
"docs": results.get("docs", []),
|
||||||
|
"name": searchQuery,
|
||||||
|
"type": "web_search",
|
||||||
|
"urls": results["filenames"],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
form_data["files"] = files
|
form_data["files"] = files
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
@ -518,6 +519,7 @@ async def chat_completion_files_handler(
|
|||||||
sources = []
|
sources = []
|
||||||
|
|
||||||
if files := body.get("metadata", {}).get("files", None):
|
if files := body.get("metadata", {}).get("files", None):
|
||||||
|
queries = []
|
||||||
try:
|
try:
|
||||||
queries_response = await generate_queries(
|
queries_response = await generate_queries(
|
||||||
request,
|
request,
|
||||||
@ -543,8 +545,8 @@ async def chat_completion_files_handler(
|
|||||||
queries_response = {"queries": [queries_response]}
|
queries_response = {"queries": [queries_response]}
|
||||||
|
|
||||||
queries = queries_response.get("queries", [])
|
queries = queries_response.get("queries", [])
|
||||||
except Exception as e:
|
except:
|
||||||
queries = []
|
pass
|
||||||
|
|
||||||
if len(queries) == 0:
|
if len(queries) == 0:
|
||||||
queries = [get_last_user_message(body["messages"])]
|
queries = [get_last_user_message(body["messages"])]
|
||||||
@ -556,6 +558,7 @@ async def chat_completion_files_handler(
|
|||||||
sources = await loop.run_in_executor(
|
sources = await loop.run_in_executor(
|
||||||
executor,
|
executor,
|
||||||
lambda: get_sources_from_files(
|
lambda: get_sources_from_files(
|
||||||
|
request=request,
|
||||||
files=files,
|
files=files,
|
||||||
queries=queries,
|
queries=queries,
|
||||||
embedding_function=lambda query: request.app.state.EMBEDDING_FUNCTION(
|
embedding_function=lambda query: request.app.state.EMBEDDING_FUNCTION(
|
||||||
@ -738,6 +741,7 @@ async def process_chat_payload(request, form_data, metadata, user, model):
|
|||||||
|
|
||||||
tool_ids = form_data.pop("tool_ids", None)
|
tool_ids = form_data.pop("tool_ids", None)
|
||||||
files = form_data.pop("files", None)
|
files = form_data.pop("files", None)
|
||||||
|
|
||||||
# Remove files duplicates
|
# Remove files duplicates
|
||||||
if files:
|
if files:
|
||||||
files = list({json.dumps(f, sort_keys=True): f for f in files}.values())
|
files = list({json.dumps(f, sort_keys=True): f for f in files}.values())
|
||||||
@ -795,8 +799,6 @@ async def process_chat_payload(request, form_data, metadata, user, model):
|
|||||||
if len(sources) > 0:
|
if len(sources) > 0:
|
||||||
context_string = ""
|
context_string = ""
|
||||||
for source_idx, source in enumerate(sources):
|
for source_idx, source in enumerate(sources):
|
||||||
source_id = source.get("source", {}).get("name", "")
|
|
||||||
|
|
||||||
if "document" in source:
|
if "document" in source:
|
||||||
for doc_idx, doc_context in enumerate(source["document"]):
|
for doc_idx, doc_context in enumerate(source["document"]):
|
||||||
context_string += f"<source><source_id>{source_idx}</source_id><source_context>{doc_context}</source_context></source>\n"
|
context_string += f"<source><source_id>{source_idx}</source_id><source_context>{doc_context}</source_context></source>\n"
|
||||||
@ -1913,7 +1915,9 @@ async def process_chat_response(
|
|||||||
)
|
)
|
||||||
|
|
||||||
log.info(f"content_blocks={content_blocks}")
|
log.info(f"content_blocks={content_blocks}")
|
||||||
log.info(f"serialize_content_blocks={serialize_content_blocks(content_blocks)}")
|
log.info(
|
||||||
|
f"serialize_content_blocks={serialize_content_blocks(content_blocks)}"
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
res = await generate_chat_completion(
|
res = await generate_chat_completion(
|
||||||
|
@ -59,6 +59,7 @@
|
|||||||
let pdfExtractImages = true;
|
let pdfExtractImages = true;
|
||||||
|
|
||||||
let RAG_FULL_CONTEXT = false;
|
let RAG_FULL_CONTEXT = false;
|
||||||
|
let BYPASS_EMBEDDING_AND_RETRIEVAL = false;
|
||||||
|
|
||||||
let enableGoogleDriveIntegration = false;
|
let enableGoogleDriveIntegration = false;
|
||||||
let enableOneDriveIntegration = false;
|
let enableOneDriveIntegration = false;
|
||||||
@ -170,12 +171,6 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const submitHandler = async () => {
|
const submitHandler = async () => {
|
||||||
await embeddingModelUpdateHandler();
|
|
||||||
|
|
||||||
if (querySettings.hybrid) {
|
|
||||||
await rerankingModelUpdateHandler();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contentExtractionEngine === 'tika' && tikaServerUrl === '') {
|
if (contentExtractionEngine === 'tika' && tikaServerUrl === '') {
|
||||||
toast.error($i18n.t('Tika Server URL required.'));
|
toast.error($i18n.t('Tika Server URL required.'));
|
||||||
return;
|
return;
|
||||||
@ -187,6 +182,15 @@
|
|||||||
toast.error($i18n.t('Document Intelligence endpoint and key required.'));
|
toast.error($i18n.t('Document Intelligence endpoint and key required.'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!BYPASS_EMBEDDING_AND_RETRIEVAL) {
|
||||||
|
await embeddingModelUpdateHandler();
|
||||||
|
|
||||||
|
if (querySettings.hybrid) {
|
||||||
|
await rerankingModelUpdateHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const res = await updateRAGConfig(localStorage.token, {
|
const res = await updateRAGConfig(localStorage.token, {
|
||||||
pdf_extract_images: pdfExtractImages,
|
pdf_extract_images: pdfExtractImages,
|
||||||
enable_google_drive_integration: enableGoogleDriveIntegration,
|
enable_google_drive_integration: enableGoogleDriveIntegration,
|
||||||
@ -196,6 +200,7 @@
|
|||||||
max_count: fileMaxCount === '' ? null : fileMaxCount
|
max_count: fileMaxCount === '' ? null : fileMaxCount
|
||||||
},
|
},
|
||||||
RAG_FULL_CONTEXT: RAG_FULL_CONTEXT,
|
RAG_FULL_CONTEXT: RAG_FULL_CONTEXT,
|
||||||
|
BYPASS_EMBEDDING_AND_RETRIEVAL: BYPASS_EMBEDDING_AND_RETRIEVAL,
|
||||||
chunk: {
|
chunk: {
|
||||||
text_splitter: textSplitter,
|
text_splitter: textSplitter,
|
||||||
chunk_overlap: chunkOverlap,
|
chunk_overlap: chunkOverlap,
|
||||||
@ -260,6 +265,7 @@
|
|||||||
chunkOverlap = res.chunk.chunk_overlap;
|
chunkOverlap = res.chunk.chunk_overlap;
|
||||||
|
|
||||||
RAG_FULL_CONTEXT = res.RAG_FULL_CONTEXT;
|
RAG_FULL_CONTEXT = res.RAG_FULL_CONTEXT;
|
||||||
|
BYPASS_EMBEDDING_AND_RETRIEVAL = res.BYPASS_EMBEDDING_AND_RETRIEVAL;
|
||||||
|
|
||||||
contentExtractionEngine = res.content_extraction.engine;
|
contentExtractionEngine = res.content_extraction.engine;
|
||||||
tikaServerUrl = res.content_extraction.tika_server_url;
|
tikaServerUrl = res.content_extraction.tika_server_url;
|
||||||
@ -328,9 +334,6 @@
|
|||||||
<select
|
<select
|
||||||
class="dark:bg-gray-900 w-fit pr-8 rounded-sm px-2 text-xs bg-transparent outline-hidden text-right"
|
class="dark:bg-gray-900 w-fit pr-8 rounded-sm px-2 text-xs bg-transparent outline-hidden text-right"
|
||||||
bind:value={contentExtractionEngine}
|
bind:value={contentExtractionEngine}
|
||||||
on:change={(e) => {
|
|
||||||
showDocumentIntelligenceConfig = e.target.value === 'document_intelligence';
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<option value="">{$i18n.t('Default')} </option>
|
<option value="">{$i18n.t('Default')} </option>
|
||||||
<option value="tika">{$i18n.t('Tika')}</option>
|
<option value="tika">{$i18n.t('Tika')}</option>
|
||||||
@ -376,151 +379,295 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class=" mb-2.5 flex w-full justify-between">
|
<div class=" mb-2.5 flex w-full justify-between">
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Text Splitter')}</div>
|
<div class=" self-center text-xs font-medium">
|
||||||
|
<Tooltip content={$i18n.t('Full Context Mode')} placement="top-start">
|
||||||
|
{$i18n.t('Bypass Embedding and Retrieval')}
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
<div class="flex items-center relative">
|
<div class="flex items-center relative">
|
||||||
<select
|
<Tooltip
|
||||||
class="dark:bg-gray-900 w-fit pr-8 rounded-sm px-2 text-xs bg-transparent outline-hidden text-right"
|
content={BYPASS_EMBEDDING_AND_RETRIEVAL
|
||||||
bind:value={textSplitter}
|
? 'Inject the entire content as context for comprehensive processing, this is recommended for complex queries.'
|
||||||
|
: 'Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.'}
|
||||||
>
|
>
|
||||||
<option value="">{$i18n.t('Default')} ({$i18n.t('Character')})</option>
|
<Switch bind:state={BYPASS_EMBEDDING_AND_RETRIEVAL} />
|
||||||
<option value="token">{$i18n.t('Token')} ({$i18n.t('Tiktoken')})</option>
|
</Tooltip>
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class=" mb-2.5 flex w-full justify-between">
|
{#if !BYPASS_EMBEDDING_AND_RETRIEVAL}
|
||||||
<div class=" flex gap-1.5 w-full">
|
<div class=" mb-2.5 flex w-full justify-between">
|
||||||
<div class=" w-full justify-between">
|
<div class=" self-center text-xs font-medium">{$i18n.t('Text Splitter')}</div>
|
||||||
<div class="self-center text-xs font-medium min-w-fit mb-1">
|
|
||||||
{$i18n.t('Chunk Size')}
|
|
||||||
</div>
|
|
||||||
<div class="self-center">
|
|
||||||
<input
|
|
||||||
class=" w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden"
|
|
||||||
type="number"
|
|
||||||
placeholder={$i18n.t('Enter Chunk Size')}
|
|
||||||
bind:value={chunkSize}
|
|
||||||
autocomplete="off"
|
|
||||||
min="0"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="w-full">
|
|
||||||
<div class=" self-center text-xs font-medium min-w-fit mb-1">
|
|
||||||
{$i18n.t('Chunk Overlap')}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="self-center">
|
|
||||||
<input
|
|
||||||
class="w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden"
|
|
||||||
type="number"
|
|
||||||
placeholder={$i18n.t('Enter Chunk Overlap')}
|
|
||||||
bind:value={chunkOverlap}
|
|
||||||
autocomplete="off"
|
|
||||||
min="0"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<div class=" mb-2.5 text-base font-medium">{$i18n.t('Embedding')}</div>
|
|
||||||
|
|
||||||
<hr class=" border-gray-100 dark:border-gray-850 my-2" />
|
|
||||||
|
|
||||||
<div class=" mb-2.5 flex flex-col w-full justify-between">
|
|
||||||
<div class="flex w-full justify-between">
|
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Embedding Model Engine')}</div>
|
|
||||||
<div class="flex items-center relative">
|
<div class="flex items-center relative">
|
||||||
<select
|
<select
|
||||||
class="dark:bg-gray-900 w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-hidden text-right"
|
class="dark:bg-gray-900 w-fit pr-8 rounded-sm px-2 text-xs bg-transparent outline-hidden text-right"
|
||||||
bind:value={embeddingEngine}
|
bind:value={textSplitter}
|
||||||
placeholder="Select an embedding model engine"
|
|
||||||
on:change={(e) => {
|
|
||||||
if (e.target.value === 'ollama') {
|
|
||||||
embeddingModel = '';
|
|
||||||
} else if (e.target.value === 'openai') {
|
|
||||||
embeddingModel = 'text-embedding-3-small';
|
|
||||||
} else if (e.target.value === '') {
|
|
||||||
embeddingModel = 'sentence-transformers/all-MiniLM-L6-v2';
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<option value="">{$i18n.t('Default (SentenceTransformers)')}</option>
|
<option value="">{$i18n.t('Default')} ({$i18n.t('Character')})</option>
|
||||||
<option value="ollama">{$i18n.t('Ollama')}</option>
|
<option value="token">{$i18n.t('Token')} ({$i18n.t('Tiktoken')})</option>
|
||||||
<option value="openai">{$i18n.t('OpenAI')}</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if embeddingEngine === 'openai'}
|
<div class=" mb-2.5 flex w-full justify-between">
|
||||||
<div class="my-0.5 flex gap-2 pr-2">
|
<div class=" flex gap-1.5 w-full">
|
||||||
<input
|
<div class=" w-full justify-between">
|
||||||
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
<div class="self-center text-xs font-medium min-w-fit mb-1">
|
||||||
placeholder={$i18n.t('API Base URL')}
|
{$i18n.t('Chunk Size')}
|
||||||
bind:value={OpenAIUrl}
|
</div>
|
||||||
required
|
<div class="self-center">
|
||||||
/>
|
|
||||||
|
|
||||||
<SensitiveInput placeholder={$i18n.t('API Key')} bind:value={OpenAIKey} />
|
|
||||||
</div>
|
|
||||||
{:else if embeddingEngine === 'ollama'}
|
|
||||||
<div class="my-0.5 flex gap-2 pr-2">
|
|
||||||
<input
|
|
||||||
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
|
||||||
placeholder={$i18n.t('API Base URL')}
|
|
||||||
bind:value={OllamaUrl}
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SensitiveInput
|
|
||||||
placeholder={$i18n.t('API Key')}
|
|
||||||
bind:value={OllamaKey}
|
|
||||||
required={false}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class=" mb-2.5 flex flex-col w-full">
|
|
||||||
<div class=" mb-1 text-xs font-medium">{$i18n.t('Embedding Model')}</div>
|
|
||||||
|
|
||||||
<div class="">
|
|
||||||
{#if embeddingEngine === 'ollama'}
|
|
||||||
<div class="flex w-full">
|
|
||||||
<div class="flex-1 mr-2">
|
|
||||||
<input
|
<input
|
||||||
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
class=" w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden"
|
||||||
bind:value={embeddingModel}
|
type="number"
|
||||||
placeholder={$i18n.t('Set embedding model')}
|
placeholder={$i18n.t('Enter Chunk Size')}
|
||||||
required
|
bind:value={chunkSize}
|
||||||
|
autocomplete="off"
|
||||||
|
min="0"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
|
||||||
<div class="flex w-full">
|
<div class="w-full">
|
||||||
<div class="flex-1 mr-2">
|
<div class=" self-center text-xs font-medium min-w-fit mb-1">
|
||||||
<input
|
{$i18n.t('Chunk Overlap')}
|
||||||
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
|
||||||
placeholder={$i18n.t('Set embedding model (e.g. {{model}})', {
|
|
||||||
model: embeddingModel.slice(-40)
|
|
||||||
})}
|
|
||||||
bind:value={embeddingModel}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if embeddingEngine === ''}
|
<div class="self-center">
|
||||||
|
<input
|
||||||
|
class="w-full rounded-lg py-1.5 px-4 text-sm bg-gray-50 dark:text-gray-300 dark:bg-gray-850 outline-hidden"
|
||||||
|
type="number"
|
||||||
|
placeholder={$i18n.t('Enter Chunk Overlap')}
|
||||||
|
bind:value={chunkOverlap}
|
||||||
|
autocomplete="off"
|
||||||
|
min="0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if !BYPASS_EMBEDDING_AND_RETRIEVAL}
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class=" mb-2.5 text-base font-medium">{$i18n.t('Embedding')}</div>
|
||||||
|
|
||||||
|
<hr class=" border-gray-100 dark:border-gray-850 my-2" />
|
||||||
|
|
||||||
|
<div class=" mb-2.5 flex flex-col w-full justify-between">
|
||||||
|
<div class="flex w-full justify-between">
|
||||||
|
<div class=" self-center text-xs font-medium">
|
||||||
|
{$i18n.t('Embedding Model Engine')}
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center relative">
|
||||||
|
<select
|
||||||
|
class="dark:bg-gray-900 w-fit pr-8 rounded-sm px-2 p-1 text-xs bg-transparent outline-hidden text-right"
|
||||||
|
bind:value={embeddingEngine}
|
||||||
|
placeholder="Select an embedding model engine"
|
||||||
|
on:change={(e) => {
|
||||||
|
if (e.target.value === 'ollama') {
|
||||||
|
embeddingModel = '';
|
||||||
|
} else if (e.target.value === 'openai') {
|
||||||
|
embeddingModel = 'text-embedding-3-small';
|
||||||
|
} else if (e.target.value === '') {
|
||||||
|
embeddingModel = 'sentence-transformers/all-MiniLM-L6-v2';
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<option value="">{$i18n.t('Default (SentenceTransformers)')}</option>
|
||||||
|
<option value="ollama">{$i18n.t('Ollama')}</option>
|
||||||
|
<option value="openai">{$i18n.t('OpenAI')}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if embeddingEngine === 'openai'}
|
||||||
|
<div class="my-0.5 flex gap-2 pr-2">
|
||||||
|
<input
|
||||||
|
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
||||||
|
placeholder={$i18n.t('API Base URL')}
|
||||||
|
bind:value={OpenAIUrl}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SensitiveInput placeholder={$i18n.t('API Key')} bind:value={OpenAIKey} />
|
||||||
|
</div>
|
||||||
|
{:else if embeddingEngine === 'ollama'}
|
||||||
|
<div class="my-0.5 flex gap-2 pr-2">
|
||||||
|
<input
|
||||||
|
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
||||||
|
placeholder={$i18n.t('API Base URL')}
|
||||||
|
bind:value={OllamaUrl}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
|
||||||
|
<SensitiveInput
|
||||||
|
placeholder={$i18n.t('API Key')}
|
||||||
|
bind:value={OllamaKey}
|
||||||
|
required={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class=" mb-2.5 flex flex-col w-full">
|
||||||
|
<div class=" mb-1 text-xs font-medium">{$i18n.t('Embedding Model')}</div>
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
{#if embeddingEngine === 'ollama'}
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div class="flex-1 mr-2">
|
||||||
|
<input
|
||||||
|
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
||||||
|
bind:value={embeddingModel}
|
||||||
|
placeholder={$i18n.t('Set embedding model')}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div class="flex-1 mr-2">
|
||||||
|
<input
|
||||||
|
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
||||||
|
placeholder={$i18n.t('Set embedding model (e.g. {{model}})', {
|
||||||
|
model: embeddingModel.slice(-40)
|
||||||
|
})}
|
||||||
|
bind:value={embeddingModel}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if embeddingEngine === ''}
|
||||||
|
<button
|
||||||
|
class="px-2.5 bg-transparent text-gray-800 dark:bg-transparent dark:text-gray-100 rounded-lg transition"
|
||||||
|
on:click={() => {
|
||||||
|
embeddingModelUpdateHandler();
|
||||||
|
}}
|
||||||
|
disabled={updateEmbeddingModelLoading}
|
||||||
|
>
|
||||||
|
{#if updateEmbeddingModelLoading}
|
||||||
|
<div class="self-center">
|
||||||
|
<svg
|
||||||
|
class=" w-4 h-4"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<style>
|
||||||
|
.spinner_ajPY {
|
||||||
|
transform-origin: center;
|
||||||
|
animation: spinner_AtaB 0.75s infinite linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinner_AtaB {
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<path
|
||||||
|
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
|
||||||
|
opacity=".25"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
|
||||||
|
class="spinner_ajPY"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="w-4 h-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M8.75 2.75a.75.75 0 0 0-1.5 0v5.69L5.03 6.22a.75.75 0 0 0-1.06 1.06l3.5 3.5a.75.75 0 0 0 1.06 0l3.5-3.5a.75.75 0 0 0-1.06-1.06L8.75 8.44V2.75Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3.5 9.75a.75.75 0 0 0-1.5 0v1.5A2.75 2.75 0 0 0 4.75 14h6.5A2.75 2.75 0 0 0 14 11.25v-1.5a.75.75 0 0 0-1.5 0v1.5c0 .69-.56 1.25-1.25 1.25h-6.5c-.69 0-1.25-.56-1.25-1.25v-1.5Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-1 mb-1 text-xs text-gray-400 dark:text-gray-500">
|
||||||
|
{$i18n.t(
|
||||||
|
'Warning: If you update or change your embedding model, you will need to re-import all documents.'
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if embeddingEngine === 'ollama' || embeddingEngine === 'openai'}
|
||||||
|
<div class=" mb-2.5 flex w-full justify-between">
|
||||||
|
<div class=" self-center text-xs font-medium">{$i18n.t('Embedding Batch Size')}</div>
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<input
|
||||||
|
bind:value={embeddingBatchSize}
|
||||||
|
type="number"
|
||||||
|
class=" bg-transparent text-center w-14 outline-none"
|
||||||
|
min="-2"
|
||||||
|
max="16000"
|
||||||
|
step="1"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class=" mb-2.5 flex w-full justify-between">
|
||||||
|
<div class=" self-center text-xs font-medium">{$i18n.t('Full Context Mode')}</div>
|
||||||
|
<div class="flex items-center relative">
|
||||||
|
<Tooltip
|
||||||
|
content={RAG_FULL_CONTEXT
|
||||||
|
? 'Inject entire contents as context for comprehensive processing, this is recommended for complex queries.'
|
||||||
|
: 'Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.'}
|
||||||
|
>
|
||||||
|
<Switch bind:state={RAG_FULL_CONTEXT} />
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class=" mb-2.5 flex w-full justify-between">
|
||||||
|
<div class=" self-center text-xs font-medium">{$i18n.t('Hybrid Search')}</div>
|
||||||
|
<div class="flex items-center relative">
|
||||||
|
<Switch
|
||||||
|
bind:state={querySettings.hybrid}
|
||||||
|
on:change={() => {
|
||||||
|
toggleHybridSearch();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if querySettings.hybrid === true}
|
||||||
|
<div class=" mb-2.5 flex flex-col w-full">
|
||||||
|
<div class=" mb-1 text-xs font-medium">{$i18n.t('Reranking Model')}</div>
|
||||||
|
|
||||||
|
<div class="">
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div class="flex-1 mr-2">
|
||||||
|
<input
|
||||||
|
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
||||||
|
placeholder={$i18n.t('Set reranking model (e.g. {{model}})', {
|
||||||
|
model: 'BAAI/bge-reranker-v2-m3'
|
||||||
|
})}
|
||||||
|
bind:value={rerankingModel}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
class="px-2.5 bg-transparent text-gray-800 dark:bg-transparent dark:text-gray-100 rounded-lg transition"
|
class="px-2.5 bg-transparent text-gray-800 dark:bg-transparent dark:text-gray-100 rounded-lg transition"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
embeddingModelUpdateHandler();
|
rerankingModelUpdateHandler();
|
||||||
}}
|
}}
|
||||||
disabled={updateEmbeddingModelLoading}
|
disabled={updateRerankingModelLoading}
|
||||||
>
|
>
|
||||||
{#if updateEmbeddingModelLoading}
|
{#if updateRerankingModelLoading}
|
||||||
<div class="self-center">
|
<div class="self-center">
|
||||||
<svg
|
<svg
|
||||||
class=" w-4 h-4"
|
class=" w-4 h-4"
|
||||||
@ -566,196 +713,75 @@
|
|||||||
</svg>
|
</svg>
|
||||||
{/if}
|
{/if}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
|
|
||||||
<div class="mt-1 mb-1 text-xs text-gray-400 dark:text-gray-500">
|
|
||||||
{$i18n.t(
|
|
||||||
'Warning: If you update or change your embedding model, you will need to re-import all documents.'
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if embeddingEngine === 'ollama' || embeddingEngine === 'openai'}
|
<div class="mb-3">
|
||||||
<div class=" mb-2.5 flex w-full justify-between">
|
<div class=" mb-2.5 text-base font-medium">{$i18n.t('Retrieval')}</div>
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Embedding Batch Size')}</div>
|
|
||||||
|
|
||||||
<div class="">
|
<hr class=" border-gray-100 dark:border-gray-850 my-2" />
|
||||||
|
|
||||||
|
<div class=" mb-2.5 flex w-full justify-between">
|
||||||
|
<div class=" self-center text-xs font-medium">{$i18n.t('Top K')}</div>
|
||||||
|
<div class="flex items-center relative">
|
||||||
<input
|
<input
|
||||||
bind:value={embeddingBatchSize}
|
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
||||||
type="number"
|
type="number"
|
||||||
class=" bg-transparent text-center w-14 outline-none"
|
placeholder={$i18n.t('Enter Top K')}
|
||||||
min="-2"
|
bind:value={querySettings.k}
|
||||||
max="16000"
|
autocomplete="off"
|
||||||
step="1"
|
min="0"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class=" mb-2.5 flex w-full justify-between">
|
{#if querySettings.hybrid === true}
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Full Context Mode')}</div>
|
<div class=" mb-2.5 flex flex-col w-full justify-between">
|
||||||
<div class="flex items-center relative">
|
<div class=" flex w-full justify-between">
|
||||||
<Tooltip
|
<div class=" self-center text-xs font-medium">{$i18n.t('Minimum Score')}</div>
|
||||||
content={RAG_FULL_CONTEXT
|
<div class="flex items-center relative">
|
||||||
? 'Inject entire contents as context for comprehensive processing, this is recommended for complex queries.'
|
|
||||||
: 'Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.'}
|
|
||||||
>
|
|
||||||
<Switch bind:state={RAG_FULL_CONTEXT} />
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class=" mb-2.5 flex w-full justify-between">
|
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Hybrid Search')}</div>
|
|
||||||
<div class="flex items-center relative">
|
|
||||||
<Switch
|
|
||||||
bind:state={querySettings.hybrid}
|
|
||||||
on:change={() => {
|
|
||||||
toggleHybridSearch();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if querySettings.hybrid === true}
|
|
||||||
<div class=" mb-2.5 flex flex-col w-full">
|
|
||||||
<div class=" mb-1 text-xs font-medium">{$i18n.t('Reranking Model')}</div>
|
|
||||||
|
|
||||||
<div class="">
|
|
||||||
<div class="flex w-full">
|
|
||||||
<div class="flex-1 mr-2">
|
|
||||||
<input
|
<input
|
||||||
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
||||||
placeholder={$i18n.t('Set reranking model (e.g. {{model}})', {
|
type="number"
|
||||||
model: 'BAAI/bge-reranker-v2-m3'
|
step="0.01"
|
||||||
})}
|
placeholder={$i18n.t('Enter Score')}
|
||||||
bind:value={rerankingModel}
|
bind:value={querySettings.r}
|
||||||
|
autocomplete="off"
|
||||||
|
min="0.0"
|
||||||
|
title={$i18n.t('The score should be a value between 0.0 (0%) and 1.0 (100%).')}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<button
|
|
||||||
class="px-2.5 bg-transparent text-gray-800 dark:bg-transparent dark:text-gray-100 rounded-lg transition"
|
|
||||||
on:click={() => {
|
|
||||||
rerankingModelUpdateHandler();
|
|
||||||
}}
|
|
||||||
disabled={updateRerankingModelLoading}
|
|
||||||
>
|
|
||||||
{#if updateRerankingModelLoading}
|
|
||||||
<div class="self-center">
|
|
||||||
<svg
|
|
||||||
class=" w-4 h-4"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
fill="currentColor"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<style>
|
|
||||||
.spinner_ajPY {
|
|
||||||
transform-origin: center;
|
|
||||||
animation: spinner_AtaB 0.75s infinite linear;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spinner_AtaB {
|
|
||||||
100% {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<path
|
|
||||||
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
|
|
||||||
opacity=".25"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
|
|
||||||
class="spinner_ajPY"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
fill="currentColor"
|
|
||||||
class="w-4 h-4"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M8.75 2.75a.75.75 0 0 0-1.5 0v5.69L5.03 6.22a.75.75 0 0 0-1.06 1.06l3.5 3.5a.75.75 0 0 0 1.06 0l3.5-3.5a.75.75 0 0 0-1.06-1.06L8.75 8.44V2.75Z"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
d="M3.5 9.75a.75.75 0 0 0-1.5 0v1.5A2.75 2.75 0 0 0 4.75 14h6.5A2.75 2.75 0 0 0 14 11.25v-1.5a.75.75 0 0 0-1.5 0v1.5c0 .69-.56 1.25-1.25 1.25h-6.5c-.69 0-1.25-.56-1.25-1.25v-1.5Z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
{/if}
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="mt-1 text-xs text-gray-400 dark:text-gray-500">
|
||||||
</div>
|
{$i18n.t(
|
||||||
{/if}
|
'Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.'
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mb-3">
|
|
||||||
<div class=" mb-2.5 text-base font-medium">{$i18n.t('Query')}</div>
|
|
||||||
|
|
||||||
<hr class=" border-gray-100 dark:border-gray-850 my-2" />
|
|
||||||
|
|
||||||
<div class=" mb-2.5 flex w-full justify-between">
|
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Top K')}</div>
|
|
||||||
<div class="flex items-center relative">
|
|
||||||
<input
|
|
||||||
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
|
||||||
type="number"
|
|
||||||
placeholder={$i18n.t('Enter Top K')}
|
|
||||||
bind:value={querySettings.k}
|
|
||||||
autocomplete="off"
|
|
||||||
min="0"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{#if querySettings.hybrid === true}
|
|
||||||
<div class=" mb-2.5 flex flex-col w-full justify-between">
|
|
||||||
<div class=" flex w-full justify-between">
|
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Minimum Score')}</div>
|
|
||||||
<div class="flex items-center relative">
|
|
||||||
<input
|
|
||||||
class="flex-1 w-full rounded-lg text-sm bg-transparent outline-hidden"
|
|
||||||
type="number"
|
|
||||||
step="0.01"
|
|
||||||
placeholder={$i18n.t('Enter Score')}
|
|
||||||
bind:value={querySettings.r}
|
|
||||||
autocomplete="off"
|
|
||||||
min="0.0"
|
|
||||||
title={$i18n.t('The score should be a value between 0.0 (0%) and 1.0 (100%).')}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="mt-1 text-xs text-gray-400 dark:text-gray-500">
|
|
||||||
{$i18n.t(
|
|
||||||
'Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.'
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<div class=" mb-2.5 flex flex-col w-full justify-between">
|
|
||||||
<div class=" mb-1 text-xs font-medium">{$i18n.t('RAG Template')}</div>
|
|
||||||
<div class="flex w-full items-center relative">
|
|
||||||
<Tooltip
|
|
||||||
content={$i18n.t('Leave empty to use the default prompt, or enter a custom prompt')}
|
|
||||||
placement="top-start"
|
|
||||||
className="w-full"
|
|
||||||
>
|
|
||||||
<Textarea
|
|
||||||
bind:value={querySettings.template}
|
|
||||||
placeholder={$i18n.t(
|
|
||||||
'Leave empty to use the default prompt, or enter a custom prompt'
|
|
||||||
)}
|
)}
|
||||||
/>
|
</div>
|
||||||
</Tooltip>
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<div class=" mb-2.5 flex flex-col w-full justify-between">
|
||||||
|
<div class=" mb-1 text-xs font-medium">{$i18n.t('RAG Template')}</div>
|
||||||
|
<div class="flex w-full items-center relative">
|
||||||
|
<Tooltip
|
||||||
|
content={$i18n.t('Leave empty to use the default prompt, or enter a custom prompt')}
|
||||||
|
placement="top-start"
|
||||||
|
className="w-full"
|
||||||
|
>
|
||||||
|
<Textarea
|
||||||
|
bind:value={querySettings.template}
|
||||||
|
placeholder={$i18n.t(
|
||||||
|
'Leave empty to use the default prompt, or enter a custom prompt'
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<div class=" mb-2.5 text-base font-medium">{$i18n.t('Files')}</div>
|
<div class=" mb-2.5 text-base font-medium">{$i18n.t('Files')}</div>
|
||||||
|
@ -118,14 +118,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class=" py-0.5 flex w-full justify-between">
|
<div class=" py-0.5 flex w-full justify-between">
|
||||||
<div class=" self-center text-xs font-medium">{$i18n.t('Full Context Mode')}</div>
|
<div class=" self-center text-xs font-medium">
|
||||||
|
<Tooltip content={$i18n.t('Full Context Mode')} placement="top-start">
|
||||||
|
{$i18n.t('Bypass Embedding and Retrieval')}
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
<div class="flex items-center relative">
|
<div class="flex items-center relative">
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={webConfig.RAG_WEB_SEARCH_FULL_CONTEXT
|
content={webConfig.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL
|
||||||
? 'Inject the entire web results as context for comprehensive processing, this is recommended for complex queries.'
|
? 'Inject the entire content as context for comprehensive processing, this is recommended for complex queries.'
|
||||||
: 'Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.'}
|
: 'Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.'}
|
||||||
>
|
>
|
||||||
<Switch bind:state={webConfig.RAG_WEB_SEARCH_FULL_CONTEXT} />
|
<Switch bind:state={webConfig.BYPASS_WEB_SEARCH_EMBEDDING_AND_RETRIEVAL} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
$: {
|
$: {
|
||||||
|
console.log('sources', sources);
|
||||||
citations = sources.reduce((acc, source) => {
|
citations = sources.reduce((acc, source) => {
|
||||||
if (Object.keys(source).length === 0) {
|
if (Object.keys(source).length === 0) {
|
||||||
return acc;
|
return acc;
|
||||||
@ -53,7 +54,7 @@
|
|||||||
const distance = source.distances?.[index];
|
const distance = source.distances?.[index];
|
||||||
|
|
||||||
// Within the same citation there could be multiple documents
|
// Within the same citation there could be multiple documents
|
||||||
const id = metadata?.source ?? 'N/A';
|
const id = metadata?.source ?? source?.source?.id ?? 'N/A';
|
||||||
let _source = source?.source;
|
let _source = source?.source;
|
||||||
|
|
||||||
if (metadata?.name) {
|
if (metadata?.name) {
|
||||||
|
@ -87,7 +87,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
content={enableFullContent
|
content={enableFullContent
|
||||||
? 'Inject the entire document as context for comprehensive processing, this is recommended for complex queries.'
|
? 'Inject the entire content as context for comprehensive processing, this is recommended for complex queries.'
|
||||||
: 'Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.'}
|
: 'Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.'}
|
||||||
>
|
>
|
||||||
<div class="flex items-center gap-1.5 text-xs">
|
<div class="flex items-center gap-1.5 text-xs">
|
||||||
|
Loading…
Reference in New Issue
Block a user