Compare commits

...

2 Commits

Author SHA1 Message Date
Wenxi Onyx
453ec1c701 rebase 2025-07-02 16:34:47 -07:00
Wenxi Onyx
9460a2c93a rebase 2025-07-02 16:33:13 -07:00
13 changed files with 388 additions and 102 deletions

View File

@@ -44,6 +44,9 @@ from onyx.chat.models import UserKnowledgeFilePacket
from onyx.chat.prompt_builder.answer_prompt_builder import AnswerPromptBuilder
from onyx.chat.prompt_builder.answer_prompt_builder import default_build_system_message
from onyx.chat.prompt_builder.answer_prompt_builder import default_build_user_message
from onyx.chat.prompt_builder.citations_prompt import (
compute_max_document_tokens_for_persona,
)
from onyx.chat.user_files.parse_user_files import parse_user_files
from onyx.configs.chat_configs import CHAT_TARGET_CHUNK_PERCENTAGE
from onyx.configs.chat_configs import DISABLE_LLM_CHOOSE_SEARCH
@@ -131,13 +134,13 @@ from onyx.tools.tool_implementations.internet_search.internet_search_tool import
INTERNET_SEARCH_RESPONSE_ID,
)
from onyx.tools.tool_implementations.internet_search.internet_search_tool import (
internet_search_response_to_search_docs,
InternetSearchTool,
)
from onyx.tools.tool_implementations.internet_search.internet_search_tool import (
from onyx.tools.tool_implementations.internet_search.models import (
InternetSearchResponse,
)
from onyx.tools.tool_implementations.internet_search.internet_search_tool import (
InternetSearchTool,
from onyx.tools.tool_implementations.internet_search.utils import (
internet_search_response_to_search_docs,
)
from onyx.tools.tool_implementations.search.search_tool import (
FINAL_CONTEXT_DOCUMENTS_ID,
@@ -277,6 +280,9 @@ def _handle_search_tool_response_summary(
)
# TODO: this takes the entire internet search response and sends it to LLM --> not correct
# TODO: Internet search yields first an InternetSearchResponse to populate search results
# and then yields a list of LlmDocs that should be added to context
def _handle_internet_search_tool_response_summary(
packet: ToolResponse,
db_session: Session,
@@ -910,6 +916,16 @@ def stream_chat_message_objects(
structured_response_format=new_msg_req.structured_response_format,
)
# Temp to get a pruning config for internet search
available_tokens = compute_max_document_tokens_for_persona(
db_session=db_session,
persona=persona,
actual_user_input=message_text,
)
internet_pruning_config = document_pruning_config.copy()
internet_pruning_config.max_tokens = available_tokens
tool_dict = construct_tools(
persona=persona,
prompt_config=prompt_config,
@@ -936,6 +952,7 @@ def stream_chat_message_objects(
),
internet_search_tool_config=InternetSearchToolConfig(
answer_style_config=answer_style_config,
document_pruning_config=internet_pruning_config,
),
image_generation_tool_config=ImageGenerationToolConfig(
additional_headers=litellm_additional_headers,

View File

@@ -90,7 +90,7 @@ STOP_STREAM_PAT = os.environ.get("STOP_STREAM_PAT") or None
HARD_DELETE_CHATS = os.environ.get("HARD_DELETE_CHATS", "").lower() == "true"
# Internet Search
BING_API_KEY = os.environ.get("BING_API_KEY") or None
EXA_API_KEY = os.environ.get("EXA_API_KEY") or None
# Enable in-house model for detecting connector-based filtering in queries
ENABLE_CONNECTOR_CLASSIFIER = os.environ.get("ENABLE_CONNECTOR_CLASSIFIER", False)

View File

@@ -16,9 +16,9 @@ from sqlalchemy.orm import Session
from onyx.auth.schemas import UserRole
from onyx.configs.app_configs import DISABLE_AUTH
from onyx.configs.chat_configs import BING_API_KEY
from onyx.configs.chat_configs import CONTEXT_CHUNKS_ABOVE
from onyx.configs.chat_configs import CONTEXT_CHUNKS_BELOW
from onyx.configs.chat_configs import EXA_API_KEY
from onyx.configs.constants import NotificationType
from onyx.context.search.enums import RecencyBiasSetting
from onyx.db.constants import SLACK_BOT_PERSONA_PREFIX
@@ -695,7 +695,7 @@ def update_persona_visibility(
def validate_persona_tools(tools: list[Tool]) -> None:
for tool in tools:
if tool.name == "InternetSearchTool" and not BING_API_KEY:
if tool.name == "InternetSearchTool" and not EXA_API_KEY:
raise ValueError(
"Bing API key not found, please contact your Onyx admin to get it added!"
)

View File

@@ -45,7 +45,7 @@ BUILT_IN_TOOLS: list[InCodeToolInfo] = [
in_code_tool_id=ImageGenerationTool.__name__,
display_name=ImageGenerationTool._DISPLAY_NAME,
),
# don't show the InternetSearchTool as an option if BING_API_KEY is not available
# don't show the InternetSearchTool as an option if EXA_API_KEY is not available
*(
[
InCodeToolInfo(
@@ -58,7 +58,7 @@ BUILT_IN_TOOLS: list[InCodeToolInfo] = [
display_name=InternetSearchTool._DISPLAY_NAME,
)
]
if os.environ.get("BING_API_KEY")
if os.environ.get("EXA_API_KEY")
else []
),
]

View File

@@ -14,7 +14,7 @@ from onyx.configs.app_configs import AZURE_DALLE_API_KEY
from onyx.configs.app_configs import AZURE_DALLE_API_VERSION
from onyx.configs.app_configs import AZURE_DALLE_DEPLOYMENT_NAME
from onyx.configs.app_configs import IMAGE_MODEL_NAME
from onyx.configs.chat_configs import BING_API_KEY
from onyx.configs.chat_configs import EXA_API_KEY
from onyx.configs.model_configs import GEN_AI_TEMPERATURE
from onyx.context.search.enums import LLMEvaluationType
from onyx.context.search.enums import OptionalSearchSetting
@@ -124,6 +124,9 @@ class InternetSearchToolConfig(BaseModel):
citation_config=CitationConfig(all_docs_useful=True)
)
)
document_pruning_config: DocumentPruningConfig = Field(
default_factory=DocumentPruningConfig
)
class ImageGenerationToolConfig(BaseModel):
@@ -219,15 +222,18 @@ def construct_tools(
if not internet_search_tool_config:
internet_search_tool_config = InternetSearchToolConfig()
if not BING_API_KEY:
if not EXA_API_KEY:
raise ValueError(
"Internet search tool requires a Bing API key, please contact your Onyx admin to get it added!"
"Internet search tool requires an Exa AI API key, please contact your Onyx admin to get it added!"
)
tool_dict[db_tool_model.id] = [
InternetSearchTool(
api_key=BING_API_KEY,
api_key=EXA_API_KEY,
db_session=db_session,
llm=llm,
answer_style_config=internet_search_tool_config.answer_style_config,
prompt_config=prompt_config,
pruning_config=internet_search_tool_config.document_pruning_config,
)
]

View File

@@ -5,15 +5,26 @@ from typing import Any
from typing import cast
import httpx
from sqlalchemy.orm import Session
from onyx.chat.chat_utils import combine_message_chain
from onyx.chat.models import AnswerStyleConfig
from onyx.chat.models import LlmDoc
from onyx.chat.models import DocumentPruningConfig
from onyx.chat.models import PromptConfig
from onyx.chat.prompt_builder.answer_prompt_builder import AnswerPromptBuilder
from onyx.chat.prompt_builder.citations_prompt import compute_max_llm_input_tokens
from onyx.configs.constants import DocumentSource
from onyx.configs.model_configs import GEN_AI_HISTORY_CUTOFF
from onyx.context.search.models import SearchDoc
from onyx.configs.model_configs import GEN_AI_MODEL_FALLBACK_MAX_TOKENS
from onyx.connectors.models import Document
from onyx.connectors.models import TextSection
from onyx.db.search_settings import get_current_search_settings
from onyx.indexing.chunker import Chunker
from onyx.indexing.embedder import DefaultIndexingEmbedder
from onyx.indexing.embedder import embed_chunks_with_failure_handling
from onyx.indexing.indexing_pipeline import process_image_sections
from onyx.indexing.models import DocAwareChunk
from onyx.indexing.models import IndexChunk
from onyx.llm.interfaces import LLM
from onyx.llm.models import PreviousMessage
from onyx.llm.utils import message_to_string
@@ -26,8 +37,9 @@ from onyx.tools.tool import Tool
from onyx.tools.tool_implementations.internet_search.models import (
InternetSearchResponse,
)
from onyx.tools.tool_implementations.internet_search.models import (
InternetSearchResult,
from onyx.tools.tool_implementations.internet_search.models import InternetSearchResult
from onyx.tools.tool_implementations.internet_search.utils import (
internet_search_chunk_to_llm_doc,
)
from onyx.tools.tool_implementations.search_like_tool_utils import (
build_next_prompt_for_search_like_tool,
@@ -37,6 +49,7 @@ from onyx.tools.tool_implementations.search_like_tool_utils import (
)
from onyx.utils.logger import setup_logger
from onyx.utils.special_types import JSON_ro
from shared_configs.enums import EmbedTextType
logger = setup_logger()
@@ -66,70 +79,45 @@ Follow Up Input:
""".strip()
def llm_doc_from_internet_search_result(result: InternetSearchResult) -> LlmDoc:
return LlmDoc(
document_id=result.link,
content=result.snippet,
blurb=result.snippet,
semantic_identifier=result.link,
source_type=DocumentSource.WEB,
metadata={},
updated_at=datetime.now(),
link=result.link,
source_links={0: result.link},
match_highlights=[],
)
def internet_search_response_to_search_docs(
internet_search_response: InternetSearchResponse,
) -> list[SearchDoc]:
return [
SearchDoc(
document_id=doc.link,
chunk_ind=-1,
semantic_identifier=doc.title,
link=doc.link,
blurb=doc.snippet,
source_type=DocumentSource.NOT_APPLICABLE,
boost=0,
hidden=False,
metadata={},
score=None,
match_highlights=[],
updated_at=None,
primary_owners=[],
secondary_owners=[],
is_internet=True,
)
for doc in internet_search_response.internet_results
]
# override_kwargs is not supported for internet search tools
class InternetSearchTool(Tool[None]):
_NAME = "run_internet_search"
_DISPLAY_NAME = "Internet Search"
_DESCRIPTION = "Perform an internet search for up-to-date information."
# TODO: Tool constructor sets answerstyle to all sources relevant, but that is not true for internet search
def __init__(
self,
db_session: Session,
llm: LLM,
api_key: str,
pruning_config: DocumentPruningConfig,
answer_style_config: AnswerStyleConfig,
prompt_config: PromptConfig,
num_results: int = 10,
) -> None:
self.db_session = db_session
self.llm = llm
self.api_key = api_key
self.pruning_config = pruning_config
self.answer_style_config = answer_style_config
self.prompt_config = prompt_config
self.host = "https://api.bing.microsoft.com/v7.0"
self.host = "https://api.exa.ai"
self.headers = {
"Ocp-Apim-Subscription-Key": api_key,
"x-api-key": api_key,
"Content-Type": "application/json",
}
self.num_results = num_results
self.client = httpx.Client()
max_input_tokens = compute_max_llm_input_tokens(
llm_config=llm.config,
)
if max_input_tokens < 3 * GEN_AI_MODEL_FALLBACK_MAX_TOKENS:
self.chunks_above = 0
self.chunks_below = 0
self.chunks_above + self.chunks_below + 1
@property
def name(self) -> str:
@@ -162,6 +150,8 @@ class InternetSearchTool(Tool[None]):
},
}
"""For LLMs that don't support tool calling"""
def check_if_needs_internet_search(
self,
query: str,
@@ -211,57 +201,181 @@ class InternetSearchTool(Tool[None]):
self, *args: ToolResponse
) -> str | list[str | dict[str, Any]]:
search_response = cast(InternetSearchResponse, args[0].response)
return json.dumps(search_response.model_dump())
return json.dumps(search_response.model_dump(), default=str)
def _perform_search(self, query: str) -> InternetSearchResponse:
response = self.client.get(
f"{self.host}/search",
headers=self.headers,
params={"q": query, "count": self.num_results},
with httpx.Client(timeout=20.0) as client: # Exa search api takes ~10-15s
response = client.post(
f"{self.host}/search",
headers=self.headers,
data=json.dumps(
{
"query": query,
"type": "auto",
"numResults": self.num_results,
"contents": {
"text": True,
"livecrawl": "always",
"summary": True,
"highlights": {
"numSentences": 5,
"highlightsPerUrl": 1,
"query": "Most relevant to the question: {query}",
},
},
}
),
)
response.raise_for_status()
results = response.json()
# Exa always returns results (questionable)
search_results = results["results"]
internet_results = []
for result in search_results:
try:
# Check required fields first
required_fields = ["title", "url", "text", "summary", "highlights"]
missing_fields = [
field for field in required_fields if field not in result
]
if missing_fields:
logger.warning(
f"Missing required fields in search result: {missing_fields}"
)
continue
internet_results.append(
InternetSearchResult(
title=result["title"],
url=result["url"],
published_date=result.get(
"publishedDate", datetime.now().isoformat()
),
author=result.get("author"),
score=result.get("score"),
full_content=result["text"],
relevant_content="\n".join(result["highlights"]),
summary=result["summary"],
)
)
except Exception as e:
logger.error(f"Error processing search result: {e}")
continue
return InternetSearchResponse(
revised_query=query,
internet_results=internet_results,
)
def embed_internet_search_results(
self, results: InternetSearchResponse, embedder: DefaultIndexingEmbedder
) -> list[DocAwareChunk]:
documents: list[Document] = []
for result in results.internet_results:
# Create a document from the search result
doc = Document(
id=result.url,
sections=[TextSection(link=result.url, text=result.full_content)],
source=DocumentSource.NOT_APPLICABLE,
semantic_identifier=result.title,
metadata={
"url": result.url,
"published_date": result.published_date,
"author": result.author or "Unknown",
"score": str(result.score) if result.score else "N/A",
},
doc_updated_at=(
datetime.fromisoformat(result.published_date)
if result.published_date
else None
),
title=result.title,
)
documents.append(doc)
indexing_documents = process_image_sections(documents)
chunker = Chunker(
tokenizer=embedder.embedding_model.tokenizer,
enable_multipass=False,
enable_contextual_rag=False,
)
chunks = chunker.chunk(indexing_documents)
chunks_with_embeddings, _ = (
embed_chunks_with_failure_handling(
chunks=chunks,
embedder=embedder,
)
if chunks
else ([], [])
)
response.raise_for_status()
return chunks_with_embeddings
results = response.json()
def vector_similarity_sort(
self, query: list[float], chunks: list[IndexChunk]
) -> list[IndexChunk]:
def cosine_similarity(a: list[float], b: list[float]) -> float:
dot_product = sum(x * y for x, y in zip(a, b))
norm_a = sum(x * x for x in a) ** 0.5
norm_b = sum(x * x for x in b) ** 0.5
if norm_a == 0 or norm_b == 0:
return 0.0
return dot_product / (norm_a * norm_b)
# If no hits, Bing does not include the webPages key
search_results = (
results["webPages"]["value"][: self.num_results]
if "webPages" in results
else []
)
# Calculate similarity scores for each chunk
scored_chunks = []
for chunk in chunks:
# Use the full embedding for similarity calculation
similarity = cosine_similarity(query, chunk.embeddings.full_embedding)
scored_chunks.append((similarity, chunk))
return InternetSearchResponse(
revised_query=query,
internet_results=[
InternetSearchResult(
title=result["name"],
link=result["url"],
snippet=result["snippet"],
)
for result in search_results
],
)
# Sort chunks by similarity score in descending order
scored_chunks.sort(key=lambda x: x[0], reverse=True)
# Return just the chunks in order of similarity
return [chunk for _, chunk in scored_chunks]
def run(
self, override_kwargs: None = None, **kwargs: str
) -> Generator[ToolResponse, None, None]:
query = cast(str, kwargs["internet_search_query"])
query = kwargs["internet_search_query"]
results = self._perform_search(query)
yield ToolResponse(
id=INTERNET_SEARCH_RESPONSE_ID,
response=results,
# Yield initial search response
yield ToolResponse(id=INTERNET_SEARCH_RESPONSE_ID, response=results)
search_settings = get_current_search_settings(self.db_session)
embedder = DefaultIndexingEmbedder.from_db_search_settings(
search_settings=search_settings
)
query_embedding = embedder.embedding_model.encode(
[query], text_type=EmbedTextType.QUERY
)[0]
embedded_chunks = self.embed_internet_search_results(
results,
embedder,
)
llm_docs = [
llm_doc_from_internet_search_result(result)
for result in results.internet_results
]
sorted_chunks = self.vector_similarity_sort(query_embedding, embedded_chunks)
pruned_llm_docs = []
token_count = 0
for chunk in sorted_chunks:
chunk_token_count = len(chunk.embeddings.full_embedding)
if token_count + chunk_token_count > self.pruning_config.max_tokens:
break
token_count += chunk_token_count
pruned_llm_docs.append(internet_search_chunk_to_llm_doc(chunk))
yield ToolResponse(
id=FINAL_CONTEXT_DOCUMENTS_ID,
response=llm_docs,
response=pruned_llm_docs,
)
def final_result(self, *args: ToolResponse) -> JSON_ro:

View File

@@ -3,10 +3,17 @@ from pydantic import BaseModel
class InternetSearchResult(BaseModel):
title: str
link: str
snippet: str
url: str
published_date: str
author: str | None
score: float | None
full_content: str | None
relevant_content: str
summary: str
class InternetSearchResponse(BaseModel):
class InternetSearchResponse(
BaseModel
): # TODO: rewrite this to be closer to search tool SearchResponseSummary
revised_query: str
internet_results: list[InternetSearchResult]

View File

@@ -0,0 +1,48 @@
from onyx.chat.models import LlmDoc
from onyx.configs.constants import DocumentSource
from onyx.context.search.models import SearchDoc
from onyx.indexing.models import IndexChunk
from onyx.tools.tool_implementations.internet_search.models import (
InternetSearchResponse,
)
# TODO: Temp, shouldn't be feeding in chunks here I think, but that's what we're left with after pruning
def internet_search_chunk_to_llm_doc(chunk: IndexChunk) -> LlmDoc:
return LlmDoc(
document_id=chunk.source_document.id,
content=chunk.content,
blurb=chunk.blurb,
semantic_identifier=chunk.source_document.title,
source_type=DocumentSource.NOT_APPLICABLE,
metadata={},
updated_at=chunk.source_document.doc_updated_at,
link=chunk.source_document.id,
source_links={0: chunk.source_document.id},
match_highlights=[],
)
def internet_search_response_to_search_docs(
internet_search_response: InternetSearchResponse,
) -> list[SearchDoc]:
return [
SearchDoc(
document_id=doc.url,
chunk_ind=-1,
semantic_identifier=doc.title,
link=doc.url,
blurb=doc.summary,
source_type=DocumentSource.NOT_APPLICABLE,
boost=0,
hidden=False,
metadata={},
score=doc.score,
match_highlights=[],
updated_at=doc.published_date,
primary_owners=[],
secondary_owners=[],
is_internet=True,
)
for doc in internet_search_response.internet_results
]

View File

@@ -46,7 +46,7 @@ services:
- DISABLE_GENERATIVE_AI=${DISABLE_GENERATIVE_AI:-}
- DISABLE_LITELLM_STREAMING=${DISABLE_LITELLM_STREAMING:-}
- LITELLM_EXTRA_HEADERS=${LITELLM_EXTRA_HEADERS:-}
- BING_API_KEY=${BING_API_KEY:-}
- EXA_API_KEY=${EXA_API_KEY:-}
- DISABLE_LLM_DOC_RELEVANCE=${DISABLE_LLM_DOC_RELEVANCE:-}
- GEN_AI_API_KEY=${GEN_AI_API_KEY:-}
# if set, allows for the use of the token budget system
@@ -180,7 +180,7 @@ services:
- DISABLE_LITELLM_STREAMING=${DISABLE_LITELLM_STREAMING:-}
- LITELLM_EXTRA_HEADERS=${LITELLM_EXTRA_HEADERS:-}
- GEN_AI_API_KEY=${GEN_AI_API_KEY:-}
- BING_API_KEY=${BING_API_KEY:-}
- EXA_API_KEY=${EXA_API_KEY:-}
# Query Options
- DOC_TIME_DECAY=${DOC_TIME_DECAY:-} # Recency Bias for search results, decay at 1 / (1 + DOC_TIME_DECAY * x years)
- HYBRID_ALPHA=${HYBRID_ALPHA:-} # Hybrid Search Alpha (0 for entirely keyword, 1 for entirely vector)

View File

@@ -52,7 +52,7 @@ services:
- DISABLE_GENERATIVE_AI=${DISABLE_GENERATIVE_AI:-}
- DISABLE_LITELLM_STREAMING=${DISABLE_LITELLM_STREAMING:-}
- LITELLM_EXTRA_HEADERS=${LITELLM_EXTRA_HEADERS:-}
- BING_API_KEY=${BING_API_KEY:-}
- EXA_API_KEY=${EXA_API_KEY:-}
- DISABLE_LLM_DOC_RELEVANCE=${DISABLE_LLM_DOC_RELEVANCE:-}
- GEN_AI_API_KEY=${GEN_AI_API_KEY:-}
- TOKEN_BUDGET_GLOBALLY_ENABLED=${TOKEN_BUDGET_GLOBALLY_ENABLED:-}
@@ -162,7 +162,7 @@ services:
- DISABLE_LITELLM_STREAMING=${DISABLE_LITELLM_STREAMING:-}
- LITELLM_EXTRA_HEADERS=${LITELLM_EXTRA_HEADERS:-}
- GEN_AI_API_KEY=${GEN_AI_API_KEY:-}
- BING_API_KEY=${BING_API_KEY:-}
- EXA_API_KEY=${EXA_API_KEY:-}
# Query Options
- DOC_TIME_DECAY=${DOC_TIME_DECAY:-}
- HYBRID_ALPHA=${HYBRID_ALPHA:-}

View File

@@ -661,7 +661,7 @@ configMap:
LANGUAGE_CHAT_NAMING_HINT: ""
QA_PROMPT_OVERRIDE: ""
# Internet Search Tool
BING_API_KEY: ""
EXA_API_KEY: ""
# Don't change the NLP models unless you know what you're doing
EMBEDDING_BATCH_SIZE: ""
DOCUMENT_ENCODER_MODEL: ""

View File

@@ -0,0 +1,87 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: env-configmap
data:
# Auth Setting, also check the secrets file
AUTH_TYPE: "disabled" # Change this for production uses unless Onyx is only accessible behind VPN
ENCRYPTION_KEY_SECRET: "" # This should not be specified directly in the yaml, this is just for reference
SESSION_EXPIRE_TIME_SECONDS: "86400" # 1 Day Default
VALID_EMAIL_DOMAINS: "" # Can be something like onyx.app, as an extra double-check
SMTP_SERVER: "" # For sending verification emails, if unspecified then defaults to 'smtp.gmail.com'
SMTP_PORT: "" # For sending verification emails, if unspecified then defaults to '587'
SMTP_USER: "" # 'your-email@company.com'
SMTP_PASS: "" # 'your-gmail-password'
EMAIL_FROM: "" # 'your-email@company.com' SMTP_USER missing used instead
CORS_ALLOWED_ORIGIN: ""
# Gen AI Settings
GEN_AI_MAX_TOKENS: ""
QA_TIMEOUT: "60"
MAX_CHUNKS_FED_TO_CHAT: ""
DISABLE_LLM_DOC_RELEVANCE: ""
DISABLE_LLM_CHOOSE_SEARCH: ""
DISABLE_LLM_QUERY_REPHRASE: ""
# Query Options
DOC_TIME_DECAY: ""
HYBRID_ALPHA: ""
EDIT_KEYWORD_QUERY: ""
MULTILINGUAL_QUERY_EXPANSION: ""
LANGUAGE_HINT: ""
LANGUAGE_CHAT_NAMING_HINT: ""
QA_PROMPT_OVERRIDE: ""
# Other Services
POSTGRES_HOST: "relational-db-service"
POSTGRES_DEFAULT_SCHEMA: ""
VESPA_HOST: "document-index-service"
REDIS_HOST: "redis-service"
# Internet Search Tool
EXA_API_KEY: ""
# Don't change the NLP models unless you know what you're doing
EMBEDDING_BATCH_SIZE: ""
DOCUMENT_ENCODER_MODEL: ""
NORMALIZE_EMBEDDINGS: ""
ASYM_QUERY_PREFIX: ""
ASYM_PASSAGE_PREFIX: ""
DISABLE_RERANK_FOR_STREAMING: ""
MODEL_SERVER_HOST: "inference-model-server-service"
MODEL_SERVER_PORT: ""
INDEXING_MODEL_SERVER_HOST: "indexing-model-server-service"
MIN_THREADS_ML_MODELS: ""
# Indexing Configs
VESPA_SEARCHER_THREADS: ""
ENABLED_CONNECTOR_TYPES: ""
DISABLE_INDEX_UPDATE_ON_SWAP: ""
DASK_JOB_CLIENT_ENABLED: ""
CONTINUE_ON_CONNECTOR_FAILURE: ""
EXPERIMENTAL_CHECKPOINTING_ENABLED: ""
CONFLUENCE_CONNECTOR_LABELS_TO_SKIP: ""
JIRA_API_VERSION: ""
WEB_CONNECTOR_VALIDATE_URLS: ""
GONG_CONNECTOR_START_TIME: ""
NOTION_CONNECTOR_ENABLE_RECURSIVE_PAGE_LOOKUP: ""
MAX_DOCUMENT_CHARS: ""
MAX_FILE_SIZE_BYTES: ""
# Worker Parallelism
CELERY_WORKER_INDEXING_CONCURRENCY: ""
CELERY_WORKER_LIGHT_CONCURRENCY: ""
CELERY_WORKER_LIGHT_PREFETCH_MULTIPLIER: ""
# OnyxBot SlackBot Configs
DANSWER_BOT_DISABLE_DOCS_ONLY_ANSWER: ""
DANSWER_BOT_DISPLAY_ERROR_MSGS: ""
DANSWER_BOT_RESPOND_EVERY_CHANNEL: ""
DANSWER_BOT_DISABLE_COT: "" # Currently unused
NOTIFY_SLACKBOT_NO_ANSWER: ""
# Logging
# Optional Telemetry, please keep it on (nothing sensitive is collected)? <3
# https://docs.onyx.app/more/telemetry
DISABLE_TELEMETRY: ""
LOG_LEVEL: ""
LOG_ALL_MODEL_INTERACTIONS: ""
LOG_DANSWER_MODEL_INTERACTIONS: ""
LOG_VESPA_TIMING_INFORMATION: ""
# Shared or Non-backend Related
INTERNAL_URL: "http://api-server-service:80" # for web server
WEB_DOMAIN: "http://localhost:3000" # for web server and api server
DOMAIN: "localhost" # for nginx
# Chat Configs
HARD_DELETE_CHATS: ""

View File

@@ -518,6 +518,13 @@ export function AssistantEditor({
.map((toolId) => Number(toolId))
.filter((toolId) => values.enabled_tools_map[toolId]);
if (
internetSearchTool &&
values.enabled_tools_map[internetSearchTool.id]
) {
formikHelpers.setFieldValue("datetime_aware", true); // Auto-toggle so internet search has access to current date
}
const searchToolEnabled = searchTool
? enabledTools.includes(searchTool.id)
: false;