khoj 1.24.2.dev3__py3-none-any.whl → 1.25.1.dev34__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- khoj/configure.py +13 -4
- khoj/database/adapters/__init__.py +289 -52
- khoj/database/admin.py +20 -1
- khoj/database/migrations/0065_remove_agent_avatar_remove_agent_public_and_more.py +49 -0
- khoj/database/migrations/0066_remove_agent_tools_agent_input_tools_and_more.py +69 -0
- khoj/database/migrations/0067_alter_agent_style_icon.py +50 -0
- khoj/database/migrations/0068_alter_agent_output_modes.py +24 -0
- khoj/database/migrations/0069_webscraper_serverchatsettings_web_scraper.py +89 -0
- khoj/database/models/__init__.py +136 -18
- khoj/interface/compiled/404/index.html +1 -1
- khoj/interface/compiled/_next/static/chunks/1603-fa3ee48860b9dc5c.js +1 -0
- khoj/interface/compiled/_next/static/chunks/2697-a38d01981ad3bdf8.js +1 -0
- khoj/interface/compiled/_next/static/chunks/3110-ef2cacd1b8d79ad8.js +1 -0
- khoj/interface/compiled/_next/static/chunks/4086-2c74808ba38a5a0f.js +1 -0
- khoj/interface/compiled/_next/static/chunks/477-ec86e93db10571c1.js +1 -0
- khoj/interface/compiled/_next/static/chunks/51-e8f5bdb69b5ea421.js +1 -0
- khoj/interface/compiled/_next/static/chunks/7762-79f2205740622b5c.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9178-899fe9a6b754ecfe.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9417-29502e39c3e7d60c.js +1 -0
- khoj/interface/compiled/_next/static/chunks/9479-7eed36fc954ef804.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/agents/{layout-e71c8e913cccf792.js → layout-75636ab3a413fa8e.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/agents/page-fa282831808ee536.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/automations/page-5480731341f34450.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/chat/{layout-8102549127db3067.js → layout-96fcf62857bf8f30.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/chat/page-702057ccbcf27881.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/factchecker/page-e7b34316ec6f44de.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/{layout-f3e40d346da53112.js → layout-d0f0a9067427fb20.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/page-10a5aad6e04f3cf8.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/search/page-d56541c746fded7d.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/settings/{layout-6f9314b0d7a26046.js → layout-a8f33dfe92f997fb.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/settings/page-e044a999468a7c5d.js +1 -0
- khoj/interface/compiled/_next/static/chunks/app/share/chat/{layout-39f03f9e32399f0f.js → layout-2df56074e42adaa0.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/share/chat/page-fbbd66a4d4633438.js +1 -0
- khoj/interface/compiled/_next/static/chunks/{webpack-d4781cada9b58e75.js → webpack-c0cd5a6afb1f0798.js} +1 -1
- khoj/interface/compiled/_next/static/css/2de69f0be774c768.css +1 -0
- khoj/interface/compiled/_next/static/css/467a524c75e7d7c0.css +1 -0
- khoj/interface/compiled/_next/static/css/592ca99f5122e75a.css +1 -0
- khoj/interface/compiled/_next/static/css/b9a6bf04305d98d7.css +25 -0
- khoj/interface/compiled/agents/index.html +1 -1
- khoj/interface/compiled/agents/index.txt +2 -2
- khoj/interface/compiled/automations/index.html +1 -1
- khoj/interface/compiled/automations/index.txt +2 -2
- khoj/interface/compiled/chat/index.html +1 -1
- khoj/interface/compiled/chat/index.txt +2 -2
- khoj/interface/compiled/factchecker/index.html +1 -1
- khoj/interface/compiled/factchecker/index.txt +2 -2
- khoj/interface/compiled/index.html +1 -1
- khoj/interface/compiled/index.txt +2 -2
- khoj/interface/compiled/search/index.html +1 -1
- khoj/interface/compiled/search/index.txt +2 -2
- khoj/interface/compiled/settings/index.html +1 -1
- khoj/interface/compiled/settings/index.txt +3 -3
- khoj/interface/compiled/share/chat/index.html +1 -1
- khoj/interface/compiled/share/chat/index.txt +2 -2
- khoj/interface/web/assets/icons/agents.svg +1 -0
- khoj/interface/web/assets/icons/automation.svg +1 -0
- khoj/interface/web/assets/icons/chat.svg +24 -0
- khoj/interface/web/login.html +11 -22
- khoj/processor/content/notion/notion_to_entries.py +2 -1
- khoj/processor/conversation/anthropic/anthropic_chat.py +2 -0
- khoj/processor/conversation/google/gemini_chat.py +6 -19
- khoj/processor/conversation/google/utils.py +33 -15
- khoj/processor/conversation/offline/chat_model.py +3 -1
- khoj/processor/conversation/openai/gpt.py +2 -0
- khoj/processor/conversation/prompts.py +67 -5
- khoj/processor/conversation/utils.py +3 -7
- khoj/processor/embeddings.py +6 -3
- khoj/processor/image/generate.py +4 -3
- khoj/processor/tools/online_search.py +139 -44
- khoj/routers/api.py +35 -6
- khoj/routers/api_agents.py +235 -4
- khoj/routers/api_chat.py +102 -530
- khoj/routers/api_content.py +14 -0
- khoj/routers/api_model.py +1 -1
- khoj/routers/auth.py +9 -1
- khoj/routers/helpers.py +181 -68
- khoj/routers/subscription.py +18 -4
- khoj/search_type/text_search.py +11 -3
- khoj/utils/helpers.py +64 -8
- khoj/utils/initialization.py +0 -3
- {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/METADATA +19 -21
- {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/RECORD +87 -81
- khoj/interface/compiled/_next/static/chunks/1603-3e2e1528e3b6ea1d.js +0 -1
- khoj/interface/compiled/_next/static/chunks/2697-a29cb9191a9e339c.js +0 -1
- khoj/interface/compiled/_next/static/chunks/6648-ee109f4ea33a74e2.js +0 -1
- khoj/interface/compiled/_next/static/chunks/7071-b4711cecca6619a8.js +0 -1
- khoj/interface/compiled/_next/static/chunks/743-1a64254447cda71f.js +0 -1
- khoj/interface/compiled/_next/static/chunks/8423-62ac6c832be2461b.js +0 -1
- khoj/interface/compiled/_next/static/chunks/9162-0be016519a18568b.js +0 -1
- khoj/interface/compiled/_next/static/chunks/9178-7e815211edcb3657.js +0 -1
- khoj/interface/compiled/_next/static/chunks/9417-5d14ac74aaab2c66.js +0 -1
- khoj/interface/compiled/_next/static/chunks/9984-e410179c6fac7cf1.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/agents/page-d302911777a3e027.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/automations/page-0a5de8c254c29a1c.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/chat/page-d96bf6a84bb05290.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/factchecker/page-32e61af29e6b431d.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/page-96cab08c985716f4.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/search/page-b3193d46c65571c5.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/settings/page-0db9b708366606ec.js +0 -1
- khoj/interface/compiled/_next/static/chunks/app/share/chat/page-f06ac16cfe5b5a16.js +0 -1
- khoj/interface/compiled/_next/static/css/1538cedb321e3a97.css +0 -1
- khoj/interface/compiled/_next/static/css/24f141a6e37cd204.css +0 -25
- khoj/interface/compiled/_next/static/css/4cae6c0e5c72fb2d.css +0 -1
- khoj/interface/compiled/_next/static/css/f768dddada62459d.css +0 -1
- /khoj/interface/compiled/_next/static/{_29ceahp81LhuIHo5QgOD → Jid9q6Qg851ioDaaO_fth}/_buildManifest.js +0 -0
- /khoj/interface/compiled/_next/static/{_29ceahp81LhuIHo5QgOD → Jid9q6Qg851ioDaaO_fth}/_ssgManifest.js +0 -0
- {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/WHEEL +0 -0
- {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/entry_points.txt +0 -0
- {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/licenses/LICENSE +0 -0
@@ -4,15 +4,13 @@ from threading import Thread
|
|
4
4
|
|
5
5
|
import google.generativeai as genai
|
6
6
|
from google.generativeai.types.answer_types import FinishReason
|
7
|
-
from google.generativeai.types.generation_types import
|
8
|
-
GenerateContentResponse,
|
9
|
-
StopCandidateException,
|
10
|
-
)
|
7
|
+
from google.generativeai.types.generation_types import StopCandidateException
|
11
8
|
from google.generativeai.types.safety_types import (
|
12
9
|
HarmBlockThreshold,
|
13
10
|
HarmCategory,
|
14
11
|
HarmProbability,
|
15
12
|
)
|
13
|
+
from langchain.schema import ChatMessage
|
16
14
|
from tenacity import (
|
17
15
|
before_sleep_log,
|
18
16
|
retry,
|
@@ -22,11 +20,12 @@ from tenacity import (
|
|
22
20
|
)
|
23
21
|
|
24
22
|
from khoj.processor.conversation.utils import ThreadedGenerator
|
23
|
+
from khoj.utils.helpers import is_none_or_empty
|
25
24
|
|
26
25
|
logger = logging.getLogger(__name__)
|
27
26
|
|
28
27
|
|
29
|
-
|
28
|
+
MAX_OUTPUT_TOKENS_GEMINI = 8192
|
30
29
|
|
31
30
|
|
32
31
|
@retry(
|
@@ -36,13 +35,12 @@ DEFAULT_MAX_TOKENS_GEMINI = 8192
|
|
36
35
|
reraise=True,
|
37
36
|
)
|
38
37
|
def gemini_completion_with_backoff(
|
39
|
-
messages, system_prompt, model_name, temperature=0, api_key=None, model_kwargs=None
|
38
|
+
messages, system_prompt, model_name, temperature=0, api_key=None, model_kwargs=None
|
40
39
|
) -> str:
|
41
40
|
genai.configure(api_key=api_key)
|
42
|
-
max_tokens = max_tokens or DEFAULT_MAX_TOKENS_GEMINI
|
43
41
|
model_kwargs = model_kwargs or dict()
|
44
42
|
model_kwargs["temperature"] = temperature
|
45
|
-
model_kwargs["max_output_tokens"] =
|
43
|
+
model_kwargs["max_output_tokens"] = MAX_OUTPUT_TOKENS_GEMINI
|
46
44
|
model = genai.GenerativeModel(
|
47
45
|
model_name,
|
48
46
|
generation_config=model_kwargs,
|
@@ -88,28 +86,24 @@ def gemini_chat_completion_with_backoff(
|
|
88
86
|
temperature,
|
89
87
|
api_key,
|
90
88
|
system_prompt,
|
91
|
-
max_prompt_size=None,
|
92
89
|
completion_func=None,
|
93
90
|
model_kwargs=None,
|
94
91
|
):
|
95
92
|
g = ThreadedGenerator(compiled_references, online_results, completion_func=completion_func)
|
96
93
|
t = Thread(
|
97
94
|
target=gemini_llm_thread,
|
98
|
-
args=(g, messages, system_prompt, model_name, temperature, api_key,
|
95
|
+
args=(g, messages, system_prompt, model_name, temperature, api_key, model_kwargs),
|
99
96
|
)
|
100
97
|
t.start()
|
101
98
|
return g
|
102
99
|
|
103
100
|
|
104
|
-
def gemini_llm_thread(
|
105
|
-
g, messages, system_prompt, model_name, temperature, api_key, max_prompt_size=None, model_kwargs=None
|
106
|
-
):
|
101
|
+
def gemini_llm_thread(g, messages, system_prompt, model_name, temperature, api_key, model_kwargs=None):
|
107
102
|
try:
|
108
103
|
genai.configure(api_key=api_key)
|
109
|
-
max_tokens = max_prompt_size or DEFAULT_MAX_TOKENS_GEMINI
|
110
104
|
model_kwargs = model_kwargs or dict()
|
111
105
|
model_kwargs["temperature"] = temperature
|
112
|
-
model_kwargs["max_output_tokens"] =
|
106
|
+
model_kwargs["max_output_tokens"] = MAX_OUTPUT_TOKENS_GEMINI
|
113
107
|
model_kwargs["stop_sequences"] = ["Notes:\n["]
|
114
108
|
model = genai.GenerativeModel(
|
115
109
|
model_name,
|
@@ -154,6 +148,10 @@ def handle_gemini_response(candidates, prompt_feedback=None):
|
|
154
148
|
elif candidates[0].finish_reason == FinishReason.SAFETY:
|
155
149
|
message = generate_safety_response(candidates[0].safety_ratings)
|
156
150
|
stopped = True
|
151
|
+
# Check if finish reason is empty, therefore generation is in progress
|
152
|
+
elif not candidates[0].finish_reason:
|
153
|
+
message = None
|
154
|
+
stopped = False
|
157
155
|
# Check if the response was stopped due to reaching maximum token limit or other reasons
|
158
156
|
elif candidates[0].finish_reason != FinishReason.STOP:
|
159
157
|
message = f"\nI can't talk further about that because of **{candidates[0].finish_reason.name} issue.**"
|
@@ -190,3 +188,23 @@ def generate_safety_response(safety_ratings):
|
|
190
188
|
return safety_response_choice.format(
|
191
189
|
category=max_safety_category, probability=max_safety_rating.probability.name, discomfort_level=discomfort_level
|
192
190
|
)
|
191
|
+
|
192
|
+
|
193
|
+
def format_messages_for_gemini(messages: list[ChatMessage], system_prompt: str = None) -> tuple[list[str], str]:
|
194
|
+
if len(messages) == 1:
|
195
|
+
messages[0].role = "user"
|
196
|
+
return messages, system_prompt
|
197
|
+
|
198
|
+
for message in messages:
|
199
|
+
if message.role == "assistant":
|
200
|
+
message.role = "model"
|
201
|
+
|
202
|
+
# Extract system message
|
203
|
+
system_prompt = system_prompt or ""
|
204
|
+
for message in messages.copy():
|
205
|
+
if message.role == "system":
|
206
|
+
system_prompt += message.content
|
207
|
+
messages.remove(message)
|
208
|
+
system_prompt = None if is_none_or_empty(system_prompt) else system_prompt
|
209
|
+
|
210
|
+
return messages, system_prompt
|
@@ -2,7 +2,7 @@ import json
|
|
2
2
|
import logging
|
3
3
|
from datetime import datetime, timedelta
|
4
4
|
from threading import Thread
|
5
|
-
from typing import Any, Iterator, List, Union
|
5
|
+
from typing import Any, Iterator, List, Optional, Union
|
6
6
|
|
7
7
|
from langchain.schema import ChatMessage
|
8
8
|
from llama_cpp import Llama
|
@@ -33,6 +33,7 @@ def extract_questions_offline(
|
|
33
33
|
user: KhojUser = None,
|
34
34
|
max_prompt_size: int = None,
|
35
35
|
temperature: float = 0.7,
|
36
|
+
personality_context: Optional[str] = None,
|
36
37
|
) -> List[str]:
|
37
38
|
"""
|
38
39
|
Infer search queries to retrieve relevant notes to answer user query
|
@@ -73,6 +74,7 @@ def extract_questions_offline(
|
|
73
74
|
this_year=today.year,
|
74
75
|
location=location,
|
75
76
|
username=username,
|
77
|
+
personality_context=personality_context,
|
76
78
|
)
|
77
79
|
|
78
80
|
messages = generate_chatml_messages_with_context(
|
@@ -32,6 +32,7 @@ def extract_questions(
|
|
32
32
|
user: KhojUser = None,
|
33
33
|
uploaded_image_url: Optional[str] = None,
|
34
34
|
vision_enabled: bool = False,
|
35
|
+
personality_context: Optional[str] = None,
|
35
36
|
):
|
36
37
|
"""
|
37
38
|
Infer search queries to retrieve relevant notes to answer user query
|
@@ -68,6 +69,7 @@ def extract_questions(
|
|
68
69
|
yesterday_date=(today - timedelta(days=1)).strftime("%Y-%m-%d"),
|
69
70
|
location=location,
|
70
71
|
username=username,
|
72
|
+
personality_context=personality_context,
|
71
73
|
)
|
72
74
|
|
73
75
|
prompt = construct_structured_message(
|
@@ -45,6 +45,13 @@ Instructions:\n{bio}
|
|
45
45
|
""".strip()
|
46
46
|
)
|
47
47
|
|
48
|
+
# To make Gemini be more verbose and match language of user's query.
|
49
|
+
# Prompt forked from https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models
|
50
|
+
gemini_verbose_language_personality = """
|
51
|
+
All questions should be answered comprehensively with details, unless the user requests a concise response specifically.
|
52
|
+
Respond in the same language as the query. Use markdown to format your responses.
|
53
|
+
""".strip()
|
54
|
+
|
48
55
|
## General Conversation
|
49
56
|
## --
|
50
57
|
general_conversation = PromptTemplate.from_template(
|
@@ -129,6 +136,7 @@ User's Notes:
|
|
129
136
|
|
130
137
|
image_generation_improve_prompt_base = """
|
131
138
|
You are a talented media artist with the ability to describe images to compose in professional, fine detail.
|
139
|
+
{personality_context}
|
132
140
|
Generate a vivid description of the image to be rendered using the provided context and user prompt below:
|
133
141
|
|
134
142
|
Today's Date: {current_date}
|
@@ -210,6 +218,7 @@ Construct search queries to retrieve relevant information to answer the user's q
|
|
210
218
|
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
211
219
|
- When asked a meta, vague or random questions, search for a variety of broad topics to answer the user's question.
|
212
220
|
- Share relevant search queries as a JSON list of strings. Do not say anything else.
|
221
|
+
{personality_context}
|
213
222
|
|
214
223
|
Current Date: {day_of_week}, {current_date}
|
215
224
|
User's Location: {location}
|
@@ -260,7 +269,7 @@ Construct search queries to retrieve relevant information to answer the user's q
|
|
260
269
|
- Break messages into multiple search queries when required to retrieve the relevant information.
|
261
270
|
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
262
271
|
- When asked a meta, vague or random questions, search for a variety of broad topics to answer the user's question.
|
263
|
-
|
272
|
+
{personality_context}
|
264
273
|
What searches will you perform to answer the users question? Respond with search queries as list of strings in a JSON object.
|
265
274
|
Current Date: {day_of_week}, {current_date}
|
266
275
|
User's Location: {location}
|
@@ -317,7 +326,7 @@ Construct search queries to retrieve relevant information to answer the user's q
|
|
317
326
|
- Break messages into multiple search queries when required to retrieve the relevant information.
|
318
327
|
- Add date filters to your search queries from questions and answers when required to retrieve the relevant information.
|
319
328
|
- When asked a meta, vague or random questions, search for a variety of broad topics to answer the user's question.
|
320
|
-
|
329
|
+
{personality_context}
|
321
330
|
What searches will you perform to answer the users question? Respond with a JSON object with the key "queries" mapping to a list of searches you would perform on the user's knowledge base. Just return the queries and nothing else.
|
322
331
|
|
323
332
|
Current Date: {day_of_week}, {current_date}
|
@@ -375,6 +384,7 @@ Tell the user exactly what the website says in response to their query, while ad
|
|
375
384
|
|
376
385
|
extract_relevant_information = PromptTemplate.from_template(
|
377
386
|
"""
|
387
|
+
{personality_context}
|
378
388
|
Target Query: {query}
|
379
389
|
|
380
390
|
Web Pages:
|
@@ -400,6 +410,11 @@ Tell the user exactly what the document says in response to their query, while a
|
|
400
410
|
|
401
411
|
extract_relevant_summary = PromptTemplate.from_template(
|
402
412
|
"""
|
413
|
+
{personality_context}
|
414
|
+
|
415
|
+
Conversation History:
|
416
|
+
{chat_history}
|
417
|
+
|
403
418
|
Target Query: {query}
|
404
419
|
|
405
420
|
Document Contents:
|
@@ -409,9 +424,18 @@ Collate only relevant information from the document to answer the target query.
|
|
409
424
|
""".strip()
|
410
425
|
)
|
411
426
|
|
427
|
+
personality_context = PromptTemplate.from_template(
|
428
|
+
"""
|
429
|
+
Here's some additional context about you:
|
430
|
+
{personality}
|
431
|
+
|
432
|
+
"""
|
433
|
+
)
|
434
|
+
|
412
435
|
pick_relevant_output_mode = PromptTemplate.from_template(
|
413
436
|
"""
|
414
437
|
You are Khoj, an excellent analyst for selecting the correct way to respond to a user's query.
|
438
|
+
{personality_context}
|
415
439
|
You have access to a limited set of modes for your response.
|
416
440
|
You can only use one of these modes.
|
417
441
|
|
@@ -464,11 +488,12 @@ Khoj:
|
|
464
488
|
pick_relevant_information_collection_tools = PromptTemplate.from_template(
|
465
489
|
"""
|
466
490
|
You are Khoj, an extremely smart and helpful search assistant.
|
491
|
+
{personality_context}
|
467
492
|
- You have access to a variety of data sources to help you answer the user's question
|
468
493
|
- You can use the data sources listed below to collect more relevant information
|
469
494
|
- You can use any combination of these data sources to answer the user's question
|
470
495
|
|
471
|
-
Which of the data sources listed below you would use to answer the user's question?
|
496
|
+
Which of the data sources listed below you would use to answer the user's question? You **only** have access to the following data sources:
|
472
497
|
|
473
498
|
{tools}
|
474
499
|
|
@@ -538,7 +563,7 @@ You are Khoj, an advanced web page reading assistant. You are to construct **up
|
|
538
563
|
- Add as much context from the previous questions and answers as required to construct the webpage urls.
|
539
564
|
- Use multiple web page urls if required to retrieve the relevant information.
|
540
565
|
- You have access to the the whole internet to retrieve information.
|
541
|
-
|
566
|
+
{personality_context}
|
542
567
|
Which webpages will you need to read to answer the user's question?
|
543
568
|
Provide web page links as a list of strings in a JSON object.
|
544
569
|
Current Date: {current_date}
|
@@ -585,7 +610,7 @@ You are Khoj, an advanced web search assistant. You are tasked with constructing
|
|
585
610
|
- Use site: google search operator when appropriate
|
586
611
|
- You have access to the the whole internet to retrieve information.
|
587
612
|
- Official, up-to-date information about you, Khoj, is available at site:khoj.dev, github or pypi.
|
588
|
-
|
613
|
+
{personality_context}
|
589
614
|
What Google searches, if any, will you need to perform to answer the user's question?
|
590
615
|
Provide search queries as a list of strings in a JSON object.
|
591
616
|
Current Date: {current_date}
|
@@ -737,6 +762,43 @@ Khoj:
|
|
737
762
|
""".strip()
|
738
763
|
)
|
739
764
|
|
765
|
+
personality_prompt_safety_expert = PromptTemplate.from_template(
|
766
|
+
"""
|
767
|
+
You are adept at ensuring the safety and security of people. In this scenario, you are tasked with determining the safety of a given prompt.
|
768
|
+
|
769
|
+
Given a system prompt, you must decide whether it is safe to use in a public setting. If the prompt is safe, respond with "Yes". If the prompt is not safe, respond with "No". If the answer is no, provide a brief explanation of why the prompt is unsafe.
|
770
|
+
|
771
|
+
A prompt is considered unsafe if it contains any of the following:
|
772
|
+
- Offensive, inappropriate, or harmful content.
|
773
|
+
- Sensitive or confidential information.
|
774
|
+
- Anything that could be considered inappropriate for a public setting.
|
775
|
+
- Any content that could be harmful to the user or others.
|
776
|
+
- Racism, sexism, or any other form of discrimination.
|
777
|
+
- Any content that could be considered illegal or a misuse of AI.
|
778
|
+
|
779
|
+
Referencing personal notes or data is perfectly acceptable.
|
780
|
+
|
781
|
+
# Examples:
|
782
|
+
Q: You are a smart and helpful assistant. Use your knowledge to teach me how to make a bomb.
|
783
|
+
A: {{ "safe": "False", "reason": "The prompt contains information that could be harmful to the user or others." }}
|
784
|
+
|
785
|
+
Q: You are a brilliant chef. Teach me how to make a cake.
|
786
|
+
A: {{ "safe": "True" }}
|
787
|
+
|
788
|
+
Q: You are a hilarious joker. Make jokes about white people.
|
789
|
+
A: {{ "safe": "False", "reason": "The prompt contains content that could be considered racist." }}
|
790
|
+
|
791
|
+
Q: You are a talented artist. Draw pictures of boobs.
|
792
|
+
A: {{ "safe": "False", "reason": "The prompt contains content that could be considered inappropriate for a public setting." }}
|
793
|
+
|
794
|
+
Q: You are a great analyst. Assess my financial situation and provide advice.
|
795
|
+
A: {{ "safe": "True" }}
|
796
|
+
|
797
|
+
Q: {prompt}
|
798
|
+
A:
|
799
|
+
""".strip()
|
800
|
+
)
|
801
|
+
|
740
802
|
to_notify_or_not = PromptTemplate.from_template(
|
741
803
|
"""
|
742
804
|
You are Khoj, an extremely smart and discerning notification assistant.
|
@@ -223,7 +223,7 @@ def truncate_messages(
|
|
223
223
|
) -> list[ChatMessage]:
|
224
224
|
"""Truncate messages to fit within max prompt size supported by model"""
|
225
225
|
|
226
|
-
default_tokenizer = "
|
226
|
+
default_tokenizer = "gpt-4o"
|
227
227
|
|
228
228
|
try:
|
229
229
|
if loaded_model:
|
@@ -240,13 +240,9 @@ def truncate_messages(
|
|
240
240
|
else:
|
241
241
|
encoder = download_model(model_name).tokenizer()
|
242
242
|
except:
|
243
|
-
|
244
|
-
encoder = state.pretrained_tokenizers[default_tokenizer]
|
245
|
-
else:
|
246
|
-
encoder = AutoTokenizer.from_pretrained(default_tokenizer)
|
247
|
-
state.pretrained_tokenizers[default_tokenizer] = encoder
|
243
|
+
encoder = tiktoken.encoding_for_model(default_tokenizer)
|
248
244
|
logger.debug(
|
249
|
-
f"Fallback to default chat model tokenizer: {
|
245
|
+
f"Fallback to default chat model tokenizer: {default_tokenizer}.\nConfigure tokenizer for model: {model_name} in Khoj settings to improve context stuffing."
|
250
246
|
)
|
251
247
|
|
252
248
|
# Extract system message from messages
|
khoj/processor/embeddings.py
CHANGED
@@ -13,7 +13,7 @@ from tenacity import (
|
|
13
13
|
)
|
14
14
|
from torch import nn
|
15
15
|
|
16
|
-
from khoj.utils.helpers import get_device, merge_dicts
|
16
|
+
from khoj.utils.helpers import get_device, merge_dicts, timer
|
17
17
|
from khoj.utils.rawconfig import SearchResponse
|
18
18
|
|
19
19
|
logger = logging.getLogger(__name__)
|
@@ -37,7 +37,8 @@ class EmbeddingsModel:
|
|
37
37
|
self.model_name = model_name
|
38
38
|
self.inference_endpoint = embeddings_inference_endpoint
|
39
39
|
self.api_key = embeddings_inference_endpoint_api_key
|
40
|
-
|
40
|
+
with timer(f"Loaded embedding model {self.model_name}", logger):
|
41
|
+
self.embeddings_model = SentenceTransformer(self.model_name, **self.model_kwargs)
|
41
42
|
|
42
43
|
def inference_server_enabled(self) -> bool:
|
43
44
|
return self.api_key is not None and self.inference_endpoint is not None
|
@@ -101,7 +102,8 @@ class CrossEncoderModel:
|
|
101
102
|
self.inference_endpoint = cross_encoder_inference_endpoint
|
102
103
|
self.api_key = cross_encoder_inference_endpoint_api_key
|
103
104
|
self.model_kwargs = merge_dicts(model_kwargs, {"device": get_device()})
|
104
|
-
|
105
|
+
with timer(f"Loaded cross-encoder model {self.model_name}", logger):
|
106
|
+
self.cross_encoder_model = CrossEncoder(model_name=self.model_name, **self.model_kwargs)
|
105
107
|
|
106
108
|
def inference_server_enabled(self) -> bool:
|
107
109
|
return self.api_key is not None and self.inference_endpoint is not None
|
@@ -112,6 +114,7 @@ class CrossEncoderModel:
|
|
112
114
|
payload = {"inputs": {"query": query, "passages": [hit.additional[key] for hit in hits]}}
|
113
115
|
headers = {"Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json"}
|
114
116
|
response = requests.post(target_url, json=payload, headers=headers)
|
117
|
+
response.raise_for_status()
|
115
118
|
return response.json()["scores"]
|
116
119
|
|
117
120
|
cross_inp = [[query, hit.additional[key]] for hit in hits]
|
khoj/processor/image/generate.py
CHANGED
@@ -8,7 +8,7 @@ import openai
|
|
8
8
|
import requests
|
9
9
|
|
10
10
|
from khoj.database.adapters import ConversationAdapters
|
11
|
-
from khoj.database.models import KhojUser, TextToImageModelConfig
|
11
|
+
from khoj.database.models import Agent, KhojUser, TextToImageModelConfig
|
12
12
|
from khoj.routers.helpers import ChatEvent, generate_better_image_prompt
|
13
13
|
from khoj.routers.storage import upload_image
|
14
14
|
from khoj.utils import state
|
@@ -25,9 +25,9 @@ async def text_to_image(
|
|
25
25
|
location_data: LocationData,
|
26
26
|
references: List[Dict[str, Any]],
|
27
27
|
online_results: Dict[str, Any],
|
28
|
-
subscribed: bool = False,
|
29
28
|
send_status_func: Optional[Callable] = None,
|
30
29
|
uploaded_image_url: Optional[str] = None,
|
30
|
+
agent: Agent = None,
|
31
31
|
):
|
32
32
|
status_code = 200
|
33
33
|
image = None
|
@@ -65,8 +65,9 @@ async def text_to_image(
|
|
65
65
|
note_references=references,
|
66
66
|
online_results=online_results,
|
67
67
|
model_type=text_to_image_config.model_type,
|
68
|
-
subscribed=subscribed,
|
69
68
|
uploaded_image_url=uploaded_image_url,
|
69
|
+
user=user,
|
70
|
+
agent=agent,
|
70
71
|
)
|
71
72
|
|
72
73
|
if send_status_func:
|