khoj 1.25.1.dev9__py3-none-any.whl → 1.25.1.dev14__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/database/adapters/__init__.py +9 -9
- khoj/database/admin.py +2 -1
- khoj/interface/compiled/404/index.html +1 -1
- khoj/interface/compiled/_next/static/chunks/app/agents/{layout-e71c8e913cccf792.js → layout-75636ab3a413fa8e.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/chat/{layout-8102549127db3067.js → layout-96fcf62857bf8f30.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/{layout-f3e40d346da53112.js → layout-d0f0a9067427fb20.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/settings/{layout-6f9314b0d7a26046.js → layout-a8f33dfe92f997fb.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/app/share/chat/{layout-39f03f9e32399f0f.js → layout-2df56074e42adaa0.js} +1 -1
- khoj/interface/compiled/_next/static/chunks/{webpack-462819dcfa6a1e2b.js → webpack-3875a06385370d08.js} +1 -1
- khoj/interface/compiled/_next/static/css/467a524c75e7d7c0.css +1 -0
- khoj/interface/compiled/agents/index.html +1 -1
- khoj/interface/compiled/agents/index.txt +1 -1
- khoj/interface/compiled/automations/index.html +1 -1
- khoj/interface/compiled/automations/index.txt +1 -1
- khoj/interface/compiled/chat/index.html +1 -1
- khoj/interface/compiled/chat/index.txt +1 -1
- khoj/interface/compiled/factchecker/index.html +1 -1
- khoj/interface/compiled/factchecker/index.txt +1 -1
- khoj/interface/compiled/index.html +1 -1
- khoj/interface/compiled/index.txt +1 -1
- khoj/interface/compiled/search/index.html +1 -1
- khoj/interface/compiled/search/index.txt +1 -1
- khoj/interface/compiled/settings/index.html +1 -1
- khoj/interface/compiled/settings/index.txt +2 -2
- khoj/interface/compiled/share/chat/index.html +1 -1
- khoj/interface/compiled/share/chat/index.txt +1 -1
- khoj/processor/conversation/google/utils.py +4 -0
- khoj/processor/tools/online_search.py +0 -2
- khoj/routers/api_chat.py +0 -481
- {khoj-1.25.1.dev9.dist-info → khoj-1.25.1.dev14.dist-info}/METADATA +1 -1
- {khoj-1.25.1.dev9.dist-info → khoj-1.25.1.dev14.dist-info}/RECORD +36 -36
- khoj/interface/compiled/_next/static/css/1538cedb321e3a97.css +0 -1
- /khoj/interface/compiled/_next/static/{jRL5xyceUdI0nvEyCkgqF → y6sFTl0gpqdS79jlpmIvx}/_buildManifest.js +0 -0
- /khoj/interface/compiled/_next/static/{jRL5xyceUdI0nvEyCkgqF → y6sFTl0gpqdS79jlpmIvx}/_ssgManifest.js +0 -0
- {khoj-1.25.1.dev9.dist-info → khoj-1.25.1.dev14.dist-info}/WHEEL +0 -0
- {khoj-1.25.1.dev9.dist-info → khoj-1.25.1.dev14.dist-info}/entry_points.txt +0 -0
- {khoj-1.25.1.dev9.dist-info → khoj-1.25.1.dev14.dist-info}/licenses/LICENSE +0 -0
khoj/routers/api_chat.py
CHANGED
@@ -885,7 +885,6 @@ async def chat(
|
|
885
885
|
meta_log,
|
886
886
|
location,
|
887
887
|
user,
|
888
|
-
subscribed,
|
889
888
|
partial(send_event, ChatEvent.STATUS),
|
890
889
|
custom_filters,
|
891
890
|
uploaded_image_url=uploaded_image_url,
|
@@ -910,7 +909,6 @@ async def chat(
|
|
910
909
|
meta_log,
|
911
910
|
location,
|
912
911
|
user,
|
913
|
-
subscribed,
|
914
912
|
partial(send_event, ChatEvent.STATUS),
|
915
913
|
uploaded_image_url=uploaded_image_url,
|
916
914
|
agent=agent,
|
@@ -1048,482 +1046,3 @@ async def chat(
|
|
1048
1046
|
response_iterator = event_generator(q, image=image)
|
1049
1047
|
response_data = await read_chat_stream(response_iterator)
|
1050
1048
|
return Response(content=json.dumps(response_data), media_type="application/json", status_code=200)
|
1051
|
-
|
1052
|
-
|
1053
|
-
# Deprecated API. Remove by end of September 2024
|
1054
|
-
@api_chat.get("")
|
1055
|
-
@requires(["authenticated"])
|
1056
|
-
async def get_chat(
|
1057
|
-
request: Request,
|
1058
|
-
common: CommonQueryParams,
|
1059
|
-
q: str,
|
1060
|
-
n: int = 7,
|
1061
|
-
d: float = None,
|
1062
|
-
stream: Optional[bool] = False,
|
1063
|
-
title: Optional[str] = None,
|
1064
|
-
conversation_id: Optional[str] = None,
|
1065
|
-
city: Optional[str] = None,
|
1066
|
-
region: Optional[str] = None,
|
1067
|
-
country: Optional[str] = None,
|
1068
|
-
timezone: Optional[str] = None,
|
1069
|
-
image: Optional[str] = None,
|
1070
|
-
rate_limiter_per_minute=Depends(
|
1071
|
-
ApiUserRateLimiter(requests=60, subscribed_requests=60, window=60, slug="chat_minute")
|
1072
|
-
),
|
1073
|
-
rate_limiter_per_day=Depends(
|
1074
|
-
ApiUserRateLimiter(requests=600, subscribed_requests=600, window=60 * 60 * 24, slug="chat_day")
|
1075
|
-
),
|
1076
|
-
):
|
1077
|
-
# Issue a deprecation warning
|
1078
|
-
warnings.warn(
|
1079
|
-
"The 'get_chat' API endpoint is deprecated. It will be removed by the end of September 2024.",
|
1080
|
-
DeprecationWarning,
|
1081
|
-
stacklevel=2,
|
1082
|
-
)
|
1083
|
-
|
1084
|
-
async def event_generator(q: str, image: str):
|
1085
|
-
start_time = time.perf_counter()
|
1086
|
-
ttft = None
|
1087
|
-
chat_metadata: dict = {}
|
1088
|
-
connection_alive = True
|
1089
|
-
user: KhojUser = request.user.object
|
1090
|
-
subscribed: bool = has_required_scope(request, ["premium"])
|
1091
|
-
event_delimiter = "␃🔚␗"
|
1092
|
-
q = unquote(q)
|
1093
|
-
nonlocal conversation_id
|
1094
|
-
|
1095
|
-
uploaded_image_url = None
|
1096
|
-
if image:
|
1097
|
-
decoded_string = unquote(image)
|
1098
|
-
base64_data = decoded_string.split(",", 1)[1]
|
1099
|
-
image_bytes = base64.b64decode(base64_data)
|
1100
|
-
webp_image_bytes = convert_image_to_webp(image_bytes)
|
1101
|
-
try:
|
1102
|
-
uploaded_image_url = upload_image_to_bucket(webp_image_bytes, request.user.object.id)
|
1103
|
-
except:
|
1104
|
-
uploaded_image_url = None
|
1105
|
-
|
1106
|
-
async def send_event(event_type: ChatEvent, data: str | dict):
|
1107
|
-
nonlocal connection_alive, ttft
|
1108
|
-
if not connection_alive or await request.is_disconnected():
|
1109
|
-
connection_alive = False
|
1110
|
-
logger.warn(f"User {user} disconnected from {common.client} client")
|
1111
|
-
return
|
1112
|
-
try:
|
1113
|
-
if event_type == ChatEvent.END_LLM_RESPONSE:
|
1114
|
-
collect_telemetry()
|
1115
|
-
if event_type == ChatEvent.START_LLM_RESPONSE:
|
1116
|
-
ttft = time.perf_counter() - start_time
|
1117
|
-
if event_type == ChatEvent.MESSAGE:
|
1118
|
-
yield data
|
1119
|
-
elif event_type == ChatEvent.REFERENCES or stream:
|
1120
|
-
yield json.dumps({"type": event_type.value, "data": data}, ensure_ascii=False)
|
1121
|
-
except asyncio.CancelledError as e:
|
1122
|
-
connection_alive = False
|
1123
|
-
logger.warn(f"User {user} disconnected from {common.client} client: {e}")
|
1124
|
-
return
|
1125
|
-
except Exception as e:
|
1126
|
-
connection_alive = False
|
1127
|
-
logger.error(f"Failed to stream chat API response to {user} on {common.client}: {e}", exc_info=True)
|
1128
|
-
return
|
1129
|
-
finally:
|
1130
|
-
yield event_delimiter
|
1131
|
-
|
1132
|
-
async def send_llm_response(response: str):
|
1133
|
-
async for result in send_event(ChatEvent.START_LLM_RESPONSE, ""):
|
1134
|
-
yield result
|
1135
|
-
async for result in send_event(ChatEvent.MESSAGE, response):
|
1136
|
-
yield result
|
1137
|
-
async for result in send_event(ChatEvent.END_LLM_RESPONSE, ""):
|
1138
|
-
yield result
|
1139
|
-
|
1140
|
-
def collect_telemetry():
|
1141
|
-
# Gather chat response telemetry
|
1142
|
-
nonlocal chat_metadata
|
1143
|
-
latency = time.perf_counter() - start_time
|
1144
|
-
cmd_set = set([cmd.value for cmd in conversation_commands])
|
1145
|
-
chat_metadata = chat_metadata or {}
|
1146
|
-
chat_metadata["conversation_command"] = cmd_set
|
1147
|
-
chat_metadata["agent"] = conversation.agent.slug if conversation.agent else None
|
1148
|
-
chat_metadata["latency"] = f"{latency:.3f}"
|
1149
|
-
chat_metadata["ttft_latency"] = f"{ttft:.3f}"
|
1150
|
-
|
1151
|
-
logger.info(f"Chat response time to first token: {ttft:.3f} seconds")
|
1152
|
-
logger.info(f"Chat response total time: {latency:.3f} seconds")
|
1153
|
-
update_telemetry_state(
|
1154
|
-
request=request,
|
1155
|
-
telemetry_type="api",
|
1156
|
-
api="chat",
|
1157
|
-
client=request.user.client_app,
|
1158
|
-
user_agent=request.headers.get("user-agent"),
|
1159
|
-
host=request.headers.get("host"),
|
1160
|
-
metadata=chat_metadata,
|
1161
|
-
)
|
1162
|
-
|
1163
|
-
conversation_commands = [get_conversation_command(query=q, any_references=True)]
|
1164
|
-
|
1165
|
-
conversation = await ConversationAdapters.aget_conversation_by_user(
|
1166
|
-
user, client_application=request.user.client_app, conversation_id=conversation_id, title=title
|
1167
|
-
)
|
1168
|
-
if not conversation:
|
1169
|
-
async for result in send_llm_response(f"Conversation {conversation_id} not found"):
|
1170
|
-
yield result
|
1171
|
-
return
|
1172
|
-
conversation_id = conversation.id
|
1173
|
-
agent = conversation.agent if conversation.agent else None
|
1174
|
-
|
1175
|
-
await is_ready_to_chat(user)
|
1176
|
-
|
1177
|
-
user_name = await aget_user_name(user)
|
1178
|
-
location = None
|
1179
|
-
if city or region or country:
|
1180
|
-
location = LocationData(city=city, region=region, country=country)
|
1181
|
-
|
1182
|
-
if is_query_empty(q):
|
1183
|
-
async for result in send_llm_response("Please ask your query to get started."):
|
1184
|
-
yield result
|
1185
|
-
return
|
1186
|
-
|
1187
|
-
user_message_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
1188
|
-
|
1189
|
-
meta_log = conversation.conversation_log
|
1190
|
-
is_automated_task = conversation_commands == [ConversationCommand.AutomatedTask]
|
1191
|
-
|
1192
|
-
if conversation_commands == [ConversationCommand.Default] or is_automated_task:
|
1193
|
-
conversation_commands = await aget_relevant_information_sources(
|
1194
|
-
q, meta_log, is_automated_task, user=user, uploaded_image_url=uploaded_image_url
|
1195
|
-
)
|
1196
|
-
conversation_commands_str = ", ".join([cmd.value for cmd in conversation_commands])
|
1197
|
-
async for result in send_event(
|
1198
|
-
ChatEvent.STATUS, f"**Chose Data Sources to Search:** {conversation_commands_str}"
|
1199
|
-
):
|
1200
|
-
yield result
|
1201
|
-
|
1202
|
-
mode = await aget_relevant_output_modes(q, meta_log, is_automated_task, user, uploaded_image_url)
|
1203
|
-
async for result in send_event(ChatEvent.STATUS, f"**Decided Response Mode:** {mode.value}"):
|
1204
|
-
yield result
|
1205
|
-
if mode not in conversation_commands:
|
1206
|
-
conversation_commands.append(mode)
|
1207
|
-
|
1208
|
-
for cmd in conversation_commands:
|
1209
|
-
await conversation_command_rate_limiter.update_and_check_if_valid(request, cmd)
|
1210
|
-
q = q.replace(f"/{cmd.value}", "").strip()
|
1211
|
-
|
1212
|
-
used_slash_summarize = conversation_commands == [ConversationCommand.Summarize]
|
1213
|
-
file_filters = conversation.file_filters if conversation else []
|
1214
|
-
# Skip trying to summarize if
|
1215
|
-
if (
|
1216
|
-
# summarization intent was inferred
|
1217
|
-
ConversationCommand.Summarize in conversation_commands
|
1218
|
-
# and not triggered via slash command
|
1219
|
-
and not used_slash_summarize
|
1220
|
-
# but we can't actually summarize
|
1221
|
-
and len(file_filters) != 1
|
1222
|
-
):
|
1223
|
-
conversation_commands.remove(ConversationCommand.Summarize)
|
1224
|
-
elif ConversationCommand.Summarize in conversation_commands:
|
1225
|
-
response_log = ""
|
1226
|
-
if len(file_filters) == 0:
|
1227
|
-
response_log = "No files selected for summarization. Please add files using the section on the left."
|
1228
|
-
async for result in send_llm_response(response_log):
|
1229
|
-
yield result
|
1230
|
-
elif len(file_filters) > 1:
|
1231
|
-
response_log = "Only one file can be selected for summarization."
|
1232
|
-
async for result in send_llm_response(response_log):
|
1233
|
-
yield result
|
1234
|
-
else:
|
1235
|
-
try:
|
1236
|
-
file_object = await FileObjectAdapters.async_get_file_objects_by_name(user, file_filters[0])
|
1237
|
-
if len(file_object) == 0:
|
1238
|
-
response_log = "Sorry, we couldn't find the full text of this file. Please re-upload the document and try again."
|
1239
|
-
async for result in send_llm_response(response_log):
|
1240
|
-
yield result
|
1241
|
-
return
|
1242
|
-
contextual_data = " ".join([file.raw_text for file in file_object])
|
1243
|
-
if not q:
|
1244
|
-
q = "Create a general summary of the file"
|
1245
|
-
async for result in send_event(
|
1246
|
-
ChatEvent.STATUS, f"**Constructing Summary Using:** {file_object[0].file_name}"
|
1247
|
-
):
|
1248
|
-
yield result
|
1249
|
-
|
1250
|
-
response = await extract_relevant_summary(
|
1251
|
-
q,
|
1252
|
-
contextual_data,
|
1253
|
-
conversation_history=meta_log,
|
1254
|
-
user=user,
|
1255
|
-
uploaded_image_url=uploaded_image_url,
|
1256
|
-
)
|
1257
|
-
response_log = str(response)
|
1258
|
-
async for result in send_llm_response(response_log):
|
1259
|
-
yield result
|
1260
|
-
except Exception as e:
|
1261
|
-
response_log = "Error summarizing file."
|
1262
|
-
logger.error(f"Error summarizing file for {user.email}: {e}", exc_info=True)
|
1263
|
-
async for result in send_llm_response(response_log):
|
1264
|
-
yield result
|
1265
|
-
await sync_to_async(save_to_conversation_log)(
|
1266
|
-
q,
|
1267
|
-
response_log,
|
1268
|
-
user,
|
1269
|
-
meta_log,
|
1270
|
-
user_message_time,
|
1271
|
-
intent_type="summarize",
|
1272
|
-
client_application=request.user.client_app,
|
1273
|
-
conversation_id=conversation_id,
|
1274
|
-
uploaded_image_url=uploaded_image_url,
|
1275
|
-
)
|
1276
|
-
return
|
1277
|
-
|
1278
|
-
custom_filters = []
|
1279
|
-
if conversation_commands == [ConversationCommand.Help]:
|
1280
|
-
if not q:
|
1281
|
-
conversation_config = await ConversationAdapters.aget_user_conversation_config(user)
|
1282
|
-
if conversation_config == None:
|
1283
|
-
conversation_config = await ConversationAdapters.aget_default_conversation_config()
|
1284
|
-
model_type = conversation_config.model_type
|
1285
|
-
formatted_help = help_message.format(model=model_type, version=state.khoj_version, device=get_device())
|
1286
|
-
async for result in send_llm_response(formatted_help):
|
1287
|
-
yield result
|
1288
|
-
return
|
1289
|
-
# Adding specification to search online specifically on khoj.dev pages.
|
1290
|
-
custom_filters.append("site:khoj.dev")
|
1291
|
-
conversation_commands.append(ConversationCommand.Online)
|
1292
|
-
|
1293
|
-
if ConversationCommand.Automation in conversation_commands:
|
1294
|
-
try:
|
1295
|
-
automation, crontime, query_to_run, subject = await create_automation(
|
1296
|
-
q, timezone, user, request.url, meta_log
|
1297
|
-
)
|
1298
|
-
except Exception as e:
|
1299
|
-
logger.error(f"Error scheduling task {q} for {user.email}: {e}")
|
1300
|
-
error_message = f"Unable to create automation. Ensure the automation doesn't already exist."
|
1301
|
-
async for result in send_llm_response(error_message):
|
1302
|
-
yield result
|
1303
|
-
return
|
1304
|
-
|
1305
|
-
llm_response = construct_automation_created_message(automation, crontime, query_to_run, subject)
|
1306
|
-
await sync_to_async(save_to_conversation_log)(
|
1307
|
-
q,
|
1308
|
-
llm_response,
|
1309
|
-
user,
|
1310
|
-
meta_log,
|
1311
|
-
user_message_time,
|
1312
|
-
intent_type="automation",
|
1313
|
-
client_application=request.user.client_app,
|
1314
|
-
conversation_id=conversation_id,
|
1315
|
-
inferred_queries=[query_to_run],
|
1316
|
-
automation_id=automation.id,
|
1317
|
-
uploaded_image_url=uploaded_image_url,
|
1318
|
-
)
|
1319
|
-
async for result in send_llm_response(llm_response):
|
1320
|
-
yield result
|
1321
|
-
return
|
1322
|
-
|
1323
|
-
# Gather Context
|
1324
|
-
## Extract Document References
|
1325
|
-
compiled_references, inferred_queries, defiltered_query = [], [], None
|
1326
|
-
async for result in extract_references_and_questions(
|
1327
|
-
request,
|
1328
|
-
meta_log,
|
1329
|
-
q,
|
1330
|
-
(n or 7),
|
1331
|
-
d,
|
1332
|
-
conversation_id,
|
1333
|
-
conversation_commands,
|
1334
|
-
location,
|
1335
|
-
partial(send_event, ChatEvent.STATUS),
|
1336
|
-
uploaded_image_url=uploaded_image_url,
|
1337
|
-
):
|
1338
|
-
if isinstance(result, dict) and ChatEvent.STATUS in result:
|
1339
|
-
yield result[ChatEvent.STATUS]
|
1340
|
-
else:
|
1341
|
-
compiled_references.extend(result[0])
|
1342
|
-
inferred_queries.extend(result[1])
|
1343
|
-
defiltered_query = result[2]
|
1344
|
-
|
1345
|
-
if not is_none_or_empty(compiled_references):
|
1346
|
-
headings = "\n- " + "\n- ".join(set([c.get("compiled", c).split("\n")[0] for c in compiled_references]))
|
1347
|
-
# Strip only leading # from headings
|
1348
|
-
headings = headings.replace("#", "")
|
1349
|
-
async for result in send_event(ChatEvent.STATUS, f"**Found Relevant Notes**: {headings}"):
|
1350
|
-
yield result
|
1351
|
-
|
1352
|
-
online_results: Dict = dict()
|
1353
|
-
|
1354
|
-
if conversation_commands == [ConversationCommand.Notes] and not await EntryAdapters.auser_has_entries(user):
|
1355
|
-
async for result in send_llm_response(f"{no_entries_found.format()}"):
|
1356
|
-
yield result
|
1357
|
-
return
|
1358
|
-
|
1359
|
-
if ConversationCommand.Notes in conversation_commands and is_none_or_empty(compiled_references):
|
1360
|
-
conversation_commands.remove(ConversationCommand.Notes)
|
1361
|
-
|
1362
|
-
## Gather Online References
|
1363
|
-
if ConversationCommand.Online in conversation_commands:
|
1364
|
-
try:
|
1365
|
-
async for result in search_online(
|
1366
|
-
defiltered_query,
|
1367
|
-
meta_log,
|
1368
|
-
location,
|
1369
|
-
user,
|
1370
|
-
subscribed,
|
1371
|
-
partial(send_event, ChatEvent.STATUS),
|
1372
|
-
custom_filters,
|
1373
|
-
uploaded_image_url=uploaded_image_url,
|
1374
|
-
):
|
1375
|
-
if isinstance(result, dict) and ChatEvent.STATUS in result:
|
1376
|
-
yield result[ChatEvent.STATUS]
|
1377
|
-
else:
|
1378
|
-
online_results = result
|
1379
|
-
except ValueError as e:
|
1380
|
-
error_message = f"Error searching online: {e}. Attempting to respond without online results"
|
1381
|
-
logger.warning(error_message)
|
1382
|
-
async for result in send_llm_response(error_message):
|
1383
|
-
yield result
|
1384
|
-
return
|
1385
|
-
|
1386
|
-
## Gather Webpage References
|
1387
|
-
if ConversationCommand.Webpage in conversation_commands:
|
1388
|
-
try:
|
1389
|
-
async for result in read_webpages(
|
1390
|
-
defiltered_query,
|
1391
|
-
meta_log,
|
1392
|
-
location,
|
1393
|
-
user,
|
1394
|
-
subscribed,
|
1395
|
-
partial(send_event, ChatEvent.STATUS),
|
1396
|
-
uploaded_image_url=uploaded_image_url,
|
1397
|
-
):
|
1398
|
-
if isinstance(result, dict) and ChatEvent.STATUS in result:
|
1399
|
-
yield result[ChatEvent.STATUS]
|
1400
|
-
else:
|
1401
|
-
direct_web_pages = result
|
1402
|
-
webpages = []
|
1403
|
-
for query in direct_web_pages:
|
1404
|
-
if online_results.get(query):
|
1405
|
-
online_results[query]["webpages"] = direct_web_pages[query]["webpages"]
|
1406
|
-
else:
|
1407
|
-
online_results[query] = {"webpages": direct_web_pages[query]["webpages"]}
|
1408
|
-
|
1409
|
-
for webpage in direct_web_pages[query]["webpages"]:
|
1410
|
-
webpages.append(webpage["link"])
|
1411
|
-
async for result in send_event(ChatEvent.STATUS, f"**Read web pages**: {webpages}"):
|
1412
|
-
yield result
|
1413
|
-
except ValueError as e:
|
1414
|
-
logger.warning(
|
1415
|
-
f"Error directly reading webpages: {e}. Attempting to respond without online results",
|
1416
|
-
exc_info=True,
|
1417
|
-
)
|
1418
|
-
|
1419
|
-
## Send Gathered References
|
1420
|
-
async for result in send_event(
|
1421
|
-
ChatEvent.REFERENCES,
|
1422
|
-
{
|
1423
|
-
"inferredQueries": inferred_queries,
|
1424
|
-
"context": compiled_references,
|
1425
|
-
"onlineContext": online_results,
|
1426
|
-
},
|
1427
|
-
):
|
1428
|
-
yield result
|
1429
|
-
|
1430
|
-
# Generate Output
|
1431
|
-
## Generate Image Output
|
1432
|
-
if ConversationCommand.Image in conversation_commands:
|
1433
|
-
async for result in text_to_image(
|
1434
|
-
q,
|
1435
|
-
user,
|
1436
|
-
meta_log,
|
1437
|
-
location_data=location,
|
1438
|
-
references=compiled_references,
|
1439
|
-
online_results=online_results,
|
1440
|
-
send_status_func=partial(send_event, ChatEvent.STATUS),
|
1441
|
-
uploaded_image_url=uploaded_image_url,
|
1442
|
-
):
|
1443
|
-
if isinstance(result, dict) and ChatEvent.STATUS in result:
|
1444
|
-
yield result[ChatEvent.STATUS]
|
1445
|
-
else:
|
1446
|
-
image, status_code, improved_image_prompt, intent_type = result
|
1447
|
-
|
1448
|
-
if image is None or status_code != 200:
|
1449
|
-
content_obj = {
|
1450
|
-
"content-type": "application/json",
|
1451
|
-
"intentType": intent_type,
|
1452
|
-
"detail": improved_image_prompt,
|
1453
|
-
"image": image,
|
1454
|
-
}
|
1455
|
-
async for result in send_llm_response(json.dumps(content_obj)):
|
1456
|
-
yield result
|
1457
|
-
return
|
1458
|
-
|
1459
|
-
await sync_to_async(save_to_conversation_log)(
|
1460
|
-
q,
|
1461
|
-
image,
|
1462
|
-
user,
|
1463
|
-
meta_log,
|
1464
|
-
user_message_time,
|
1465
|
-
intent_type=intent_type,
|
1466
|
-
inferred_queries=[improved_image_prompt],
|
1467
|
-
client_application=request.user.client_app,
|
1468
|
-
conversation_id=conversation_id,
|
1469
|
-
compiled_references=compiled_references,
|
1470
|
-
online_results=online_results,
|
1471
|
-
uploaded_image_url=uploaded_image_url,
|
1472
|
-
)
|
1473
|
-
content_obj = {
|
1474
|
-
"intentType": intent_type,
|
1475
|
-
"inferredQueries": [improved_image_prompt],
|
1476
|
-
"image": image,
|
1477
|
-
}
|
1478
|
-
async for result in send_llm_response(json.dumps(content_obj)):
|
1479
|
-
yield result
|
1480
|
-
return
|
1481
|
-
|
1482
|
-
## Generate Text Output
|
1483
|
-
async for result in send_event(ChatEvent.STATUS, f"**Generating a well-informed response**"):
|
1484
|
-
yield result
|
1485
|
-
llm_response, chat_metadata = await agenerate_chat_response(
|
1486
|
-
defiltered_query,
|
1487
|
-
meta_log,
|
1488
|
-
conversation,
|
1489
|
-
compiled_references,
|
1490
|
-
online_results,
|
1491
|
-
inferred_queries,
|
1492
|
-
conversation_commands,
|
1493
|
-
user,
|
1494
|
-
request.user.client_app,
|
1495
|
-
conversation_id,
|
1496
|
-
location,
|
1497
|
-
user_name,
|
1498
|
-
uploaded_image_url,
|
1499
|
-
)
|
1500
|
-
|
1501
|
-
# Send Response
|
1502
|
-
async for result in send_event(ChatEvent.START_LLM_RESPONSE, ""):
|
1503
|
-
yield result
|
1504
|
-
|
1505
|
-
continue_stream = True
|
1506
|
-
iterator = AsyncIteratorWrapper(llm_response)
|
1507
|
-
async for item in iterator:
|
1508
|
-
if item is None:
|
1509
|
-
async for result in send_event(ChatEvent.END_LLM_RESPONSE, ""):
|
1510
|
-
yield result
|
1511
|
-
logger.debug("Finished streaming response")
|
1512
|
-
return
|
1513
|
-
if not connection_alive or not continue_stream:
|
1514
|
-
continue
|
1515
|
-
try:
|
1516
|
-
async for result in send_event(ChatEvent.MESSAGE, f"{item}"):
|
1517
|
-
yield result
|
1518
|
-
except Exception as e:
|
1519
|
-
continue_stream = False
|
1520
|
-
logger.info(f"User {user} disconnected. Emitting rest of responses to clear thread: {e}")
|
1521
|
-
|
1522
|
-
## Stream Text Response
|
1523
|
-
if stream:
|
1524
|
-
return StreamingResponse(event_generator(q, image=image), media_type="text/plain")
|
1525
|
-
## Non-Streaming Text Response
|
1526
|
-
else:
|
1527
|
-
response_iterator = event_generator(q, image=image)
|
1528
|
-
response_data = await read_chat_stream(response_iterator)
|
1529
|
-
return Response(content=json.dumps(response_data), media_type="application/json", status_code=200)
|