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.
Files changed (109) hide show
  1. khoj/configure.py +13 -4
  2. khoj/database/adapters/__init__.py +289 -52
  3. khoj/database/admin.py +20 -1
  4. khoj/database/migrations/0065_remove_agent_avatar_remove_agent_public_and_more.py +49 -0
  5. khoj/database/migrations/0066_remove_agent_tools_agent_input_tools_and_more.py +69 -0
  6. khoj/database/migrations/0067_alter_agent_style_icon.py +50 -0
  7. khoj/database/migrations/0068_alter_agent_output_modes.py +24 -0
  8. khoj/database/migrations/0069_webscraper_serverchatsettings_web_scraper.py +89 -0
  9. khoj/database/models/__init__.py +136 -18
  10. khoj/interface/compiled/404/index.html +1 -1
  11. khoj/interface/compiled/_next/static/chunks/1603-fa3ee48860b9dc5c.js +1 -0
  12. khoj/interface/compiled/_next/static/chunks/2697-a38d01981ad3bdf8.js +1 -0
  13. khoj/interface/compiled/_next/static/chunks/3110-ef2cacd1b8d79ad8.js +1 -0
  14. khoj/interface/compiled/_next/static/chunks/4086-2c74808ba38a5a0f.js +1 -0
  15. khoj/interface/compiled/_next/static/chunks/477-ec86e93db10571c1.js +1 -0
  16. khoj/interface/compiled/_next/static/chunks/51-e8f5bdb69b5ea421.js +1 -0
  17. khoj/interface/compiled/_next/static/chunks/7762-79f2205740622b5c.js +1 -0
  18. khoj/interface/compiled/_next/static/chunks/9178-899fe9a6b754ecfe.js +1 -0
  19. khoj/interface/compiled/_next/static/chunks/9417-29502e39c3e7d60c.js +1 -0
  20. khoj/interface/compiled/_next/static/chunks/9479-7eed36fc954ef804.js +1 -0
  21. khoj/interface/compiled/_next/static/chunks/app/agents/{layout-e71c8e913cccf792.js → layout-75636ab3a413fa8e.js} +1 -1
  22. khoj/interface/compiled/_next/static/chunks/app/agents/page-fa282831808ee536.js +1 -0
  23. khoj/interface/compiled/_next/static/chunks/app/automations/page-5480731341f34450.js +1 -0
  24. khoj/interface/compiled/_next/static/chunks/app/chat/{layout-8102549127db3067.js → layout-96fcf62857bf8f30.js} +1 -1
  25. khoj/interface/compiled/_next/static/chunks/app/chat/page-702057ccbcf27881.js +1 -0
  26. khoj/interface/compiled/_next/static/chunks/app/factchecker/page-e7b34316ec6f44de.js +1 -0
  27. khoj/interface/compiled/_next/static/chunks/app/{layout-f3e40d346da53112.js → layout-d0f0a9067427fb20.js} +1 -1
  28. khoj/interface/compiled/_next/static/chunks/app/page-10a5aad6e04f3cf8.js +1 -0
  29. khoj/interface/compiled/_next/static/chunks/app/search/page-d56541c746fded7d.js +1 -0
  30. khoj/interface/compiled/_next/static/chunks/app/settings/{layout-6f9314b0d7a26046.js → layout-a8f33dfe92f997fb.js} +1 -1
  31. khoj/interface/compiled/_next/static/chunks/app/settings/page-e044a999468a7c5d.js +1 -0
  32. khoj/interface/compiled/_next/static/chunks/app/share/chat/{layout-39f03f9e32399f0f.js → layout-2df56074e42adaa0.js} +1 -1
  33. khoj/interface/compiled/_next/static/chunks/app/share/chat/page-fbbd66a4d4633438.js +1 -0
  34. khoj/interface/compiled/_next/static/chunks/{webpack-d4781cada9b58e75.js → webpack-c0cd5a6afb1f0798.js} +1 -1
  35. khoj/interface/compiled/_next/static/css/2de69f0be774c768.css +1 -0
  36. khoj/interface/compiled/_next/static/css/467a524c75e7d7c0.css +1 -0
  37. khoj/interface/compiled/_next/static/css/592ca99f5122e75a.css +1 -0
  38. khoj/interface/compiled/_next/static/css/b9a6bf04305d98d7.css +25 -0
  39. khoj/interface/compiled/agents/index.html +1 -1
  40. khoj/interface/compiled/agents/index.txt +2 -2
  41. khoj/interface/compiled/automations/index.html +1 -1
  42. khoj/interface/compiled/automations/index.txt +2 -2
  43. khoj/interface/compiled/chat/index.html +1 -1
  44. khoj/interface/compiled/chat/index.txt +2 -2
  45. khoj/interface/compiled/factchecker/index.html +1 -1
  46. khoj/interface/compiled/factchecker/index.txt +2 -2
  47. khoj/interface/compiled/index.html +1 -1
  48. khoj/interface/compiled/index.txt +2 -2
  49. khoj/interface/compiled/search/index.html +1 -1
  50. khoj/interface/compiled/search/index.txt +2 -2
  51. khoj/interface/compiled/settings/index.html +1 -1
  52. khoj/interface/compiled/settings/index.txt +3 -3
  53. khoj/interface/compiled/share/chat/index.html +1 -1
  54. khoj/interface/compiled/share/chat/index.txt +2 -2
  55. khoj/interface/web/assets/icons/agents.svg +1 -0
  56. khoj/interface/web/assets/icons/automation.svg +1 -0
  57. khoj/interface/web/assets/icons/chat.svg +24 -0
  58. khoj/interface/web/login.html +11 -22
  59. khoj/processor/content/notion/notion_to_entries.py +2 -1
  60. khoj/processor/conversation/anthropic/anthropic_chat.py +2 -0
  61. khoj/processor/conversation/google/gemini_chat.py +6 -19
  62. khoj/processor/conversation/google/utils.py +33 -15
  63. khoj/processor/conversation/offline/chat_model.py +3 -1
  64. khoj/processor/conversation/openai/gpt.py +2 -0
  65. khoj/processor/conversation/prompts.py +67 -5
  66. khoj/processor/conversation/utils.py +3 -7
  67. khoj/processor/embeddings.py +6 -3
  68. khoj/processor/image/generate.py +4 -3
  69. khoj/processor/tools/online_search.py +139 -44
  70. khoj/routers/api.py +35 -6
  71. khoj/routers/api_agents.py +235 -4
  72. khoj/routers/api_chat.py +102 -530
  73. khoj/routers/api_content.py +14 -0
  74. khoj/routers/api_model.py +1 -1
  75. khoj/routers/auth.py +9 -1
  76. khoj/routers/helpers.py +181 -68
  77. khoj/routers/subscription.py +18 -4
  78. khoj/search_type/text_search.py +11 -3
  79. khoj/utils/helpers.py +64 -8
  80. khoj/utils/initialization.py +0 -3
  81. {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/METADATA +19 -21
  82. {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/RECORD +87 -81
  83. khoj/interface/compiled/_next/static/chunks/1603-3e2e1528e3b6ea1d.js +0 -1
  84. khoj/interface/compiled/_next/static/chunks/2697-a29cb9191a9e339c.js +0 -1
  85. khoj/interface/compiled/_next/static/chunks/6648-ee109f4ea33a74e2.js +0 -1
  86. khoj/interface/compiled/_next/static/chunks/7071-b4711cecca6619a8.js +0 -1
  87. khoj/interface/compiled/_next/static/chunks/743-1a64254447cda71f.js +0 -1
  88. khoj/interface/compiled/_next/static/chunks/8423-62ac6c832be2461b.js +0 -1
  89. khoj/interface/compiled/_next/static/chunks/9162-0be016519a18568b.js +0 -1
  90. khoj/interface/compiled/_next/static/chunks/9178-7e815211edcb3657.js +0 -1
  91. khoj/interface/compiled/_next/static/chunks/9417-5d14ac74aaab2c66.js +0 -1
  92. khoj/interface/compiled/_next/static/chunks/9984-e410179c6fac7cf1.js +0 -1
  93. khoj/interface/compiled/_next/static/chunks/app/agents/page-d302911777a3e027.js +0 -1
  94. khoj/interface/compiled/_next/static/chunks/app/automations/page-0a5de8c254c29a1c.js +0 -1
  95. khoj/interface/compiled/_next/static/chunks/app/chat/page-d96bf6a84bb05290.js +0 -1
  96. khoj/interface/compiled/_next/static/chunks/app/factchecker/page-32e61af29e6b431d.js +0 -1
  97. khoj/interface/compiled/_next/static/chunks/app/page-96cab08c985716f4.js +0 -1
  98. khoj/interface/compiled/_next/static/chunks/app/search/page-b3193d46c65571c5.js +0 -1
  99. khoj/interface/compiled/_next/static/chunks/app/settings/page-0db9b708366606ec.js +0 -1
  100. khoj/interface/compiled/_next/static/chunks/app/share/chat/page-f06ac16cfe5b5a16.js +0 -1
  101. khoj/interface/compiled/_next/static/css/1538cedb321e3a97.css +0 -1
  102. khoj/interface/compiled/_next/static/css/24f141a6e37cd204.css +0 -25
  103. khoj/interface/compiled/_next/static/css/4cae6c0e5c72fb2d.css +0 -1
  104. khoj/interface/compiled/_next/static/css/f768dddada62459d.css +0 -1
  105. /khoj/interface/compiled/_next/static/{_29ceahp81LhuIHo5QgOD → Jid9q6Qg851ioDaaO_fth}/_buildManifest.js +0 -0
  106. /khoj/interface/compiled/_next/static/{_29ceahp81LhuIHo5QgOD → Jid9q6Qg851ioDaaO_fth}/_ssgManifest.js +0 -0
  107. {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/WHEEL +0 -0
  108. {khoj-1.24.2.dev3.dist-info → khoj-1.25.1.dev34.dist-info}/entry_points.txt +0 -0
  109. {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
- DEFAULT_MAX_TOKENS_GEMINI = 8192
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, max_tokens=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"] = max_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, max_prompt_size, model_kwargs),
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"] = max_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 = "hf-internal-testing/llama-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
- if default_tokenizer in state.pretrained_tokenizers:
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: {tokenizer_name}.\nConfigure tokenizer for unsupported model: {model_name} in Khoj settings to improve context stuffing."
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
@@ -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
- self.embeddings_model = SentenceTransformer(self.model_name, **self.model_kwargs)
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
- self.cross_encoder_model = CrossEncoder(model_name=self.model_name, **self.model_kwargs)
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]
@@ -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: