This commit is contained in:
Timothy Jaeryang Baek
2026-02-04 21:07:30 -06:00
parent 6320a9aaa9
commit 8b75d34a8a

View File

@@ -2400,190 +2400,131 @@ async def process_chat_payload(request, form_data, user, metadata, model):
return form_data, metadata, events
async def process_chat_response(
request, response, form_data, user, metadata, model, events, tasks
):
async def background_tasks_handler():
message = None
async def background_tasks_handler(request, form_data, user, metadata, tasks):
event_emitter = None
event_caller = None
if (
"session_id" in metadata
and metadata["session_id"]
and "chat_id" in metadata
and metadata["chat_id"]
and "message_id" in metadata
and metadata["message_id"]
):
event_emitter = get_event_emitter(metadata)
event_caller = get_event_call(metadata)
message = None
messages = []
if "chat_id" in metadata and not metadata["chat_id"].startswith("local:"):
messages_map = Chats.get_messages_map_by_chat_id(metadata["chat_id"])
message = messages_map.get(metadata["message_id"]) if messages_map else None
message_list = get_message_list(messages_map, metadata["message_id"])
# Remove details tags and files from the messages.
# as get_message_list creates a new list, it does not affect
# the original messages outside of this handler
messages = []
for message in message_list:
content = message.get("content", "")
if isinstance(content, list):
for item in content:
if item.get("type") == "text":
content = item["text"]
break
if "chat_id" in metadata and not metadata["chat_id"].startswith("local:"):
messages_map = Chats.get_messages_map_by_chat_id(metadata["chat_id"])
message = messages_map.get(metadata["message_id"]) if messages_map else None
if isinstance(content, str):
content = re.sub(
r"<details\b[^>]*>.*?<\/details>|!\[.*?\]\(.*?\)",
"",
content,
flags=re.S | re.I,
).strip()
message_list = get_message_list(messages_map, metadata["message_id"])
messages.append(
{
**message,
"role": message.get(
"role", "assistant"
), # Safe fallback for missing role
"content": content,
}
)
else:
# Local temp chat, get the model and message from the form_data
message = get_last_user_message_item(form_data.get("messages", []))
messages = form_data.get("messages", [])
if message:
message["model"] = form_data.get("model")
# Remove details tags and files from the messages.
# as get_message_list creates a new list, it does not affect
# the original messages outside of this handler
messages = []
for message in message_list:
content = message.get("content", "")
if isinstance(content, list):
for item in content:
if item.get("type") == "text":
content = item["text"]
break
if isinstance(content, str):
content = re.sub(
r"<details\b[^>]*>.*?<\/details>|!\[.*?\]\(.*?\)",
"",
content,
flags=re.S | re.I,
).strip()
messages.append(
if message and "model" in message:
if tasks and messages:
if (
TASKS.FOLLOW_UP_GENERATION in tasks
and tasks[TASKS.FOLLOW_UP_GENERATION]
):
res = await generate_follow_ups(
request,
{
**message,
"role": message.get(
"role", "assistant"
), # Safe fallback for missing role
"content": content,
}
"model": message["model"],
"messages": messages,
"message_id": metadata["message_id"],
"chat_id": metadata["chat_id"],
},
user,
)
else:
# Local temp chat, get the model and message from the form_data
message = get_last_user_message_item(form_data.get("messages", []))
messages = form_data.get("messages", [])
if message:
message["model"] = form_data.get("model")
if message and "model" in message:
if tasks and messages:
if (
TASKS.FOLLOW_UP_GENERATION in tasks
and tasks[TASKS.FOLLOW_UP_GENERATION]
):
res = await generate_follow_ups(
request,
{
"model": message["model"],
"messages": messages,
"message_id": metadata["message_id"],
"chat_id": metadata["chat_id"],
},
user,
)
if res and isinstance(res, dict):
if len(res.get("choices", [])) == 1:
response_message = res.get("choices", [])[0].get("message", {})
if res and isinstance(res, dict):
if len(res.get("choices", [])) == 1:
response_message = res.get("choices", [])[0].get(
"message", {}
)
follow_ups_string = response_message.get(
"content"
) or response_message.get("reasoning_content", "")
else:
follow_ups_string = ""
follow_ups_string = response_message.get(
"content"
) or response_message.get("reasoning_content", "")
else:
follow_ups_string = ""
follow_ups_string = follow_ups_string[
follow_ups_string.find("{") : follow_ups_string.rfind("}") + 1
]
follow_ups_string = follow_ups_string[
follow_ups_string.find("{") : follow_ups_string.rfind("}")
+ 1
]
try:
follow_ups = json.loads(follow_ups_string).get(
"follow_ups", []
)
await event_emitter(
{
"type": "chat:message:follow_ups",
"data": {
"follow_ups": follow_ups,
},
}
)
if not metadata.get("chat_id", "").startswith("local:"):
Chats.upsert_message_to_chat_by_id_and_message_id(
metadata["chat_id"],
metadata["message_id"],
{
"followUps": follow_ups,
},
)
except Exception as e:
pass
if not metadata.get("chat_id", "").startswith(
"local:"
): # Only update titles and tags for non-temp chats
if TASKS.TITLE_GENERATION in tasks:
user_message = get_last_user_message(messages)
if user_message and len(user_message) > 100:
user_message = user_message[:100] + "..."
title = None
if tasks[TASKS.TITLE_GENERATION]:
res = await generate_title(
request,
{
"model": message["model"],
"messages": messages,
"chat_id": metadata["chat_id"],
try:
follow_ups = json.loads(follow_ups_string).get("follow_ups", [])
await event_emitter(
{
"type": "chat:message:follow_ups",
"data": {
"follow_ups": follow_ups,
},
user,
)
}
)
if res and isinstance(res, dict):
if len(res.get("choices", [])) == 1:
response_message = res.get("choices", [])[0].get(
"message", {}
)
title_string = (
response_message.get("content")
or response_message.get(
"reasoning_content",
)
or message.get("content", user_message)
)
else:
title_string = ""
title_string = title_string[
title_string.find("{") : title_string.rfind("}") + 1
]
try:
title = json.loads(title_string).get(
"title", user_message
)
except Exception as e:
title = ""
if not title:
title = messages[0].get("content", user_message)
Chats.update_chat_title_by_id(
metadata["chat_id"], title
)
await event_emitter(
{
"type": "chat:title",
"data": title,
}
)
if title == None and len(messages) == 2:
title = messages[0].get("content", user_message)
Chats.update_chat_title_by_id(metadata["chat_id"], title)
await event_emitter(
if not metadata.get("chat_id", "").startswith("local:"):
Chats.upsert_message_to_chat_by_id_and_message_id(
metadata["chat_id"],
metadata["message_id"],
{
"type": "chat:title",
"data": message.get("content", user_message),
}
"followUps": follow_ups,
},
)
if TASKS.TAGS_GENERATION in tasks and tasks[TASKS.TAGS_GENERATION]:
res = await generate_chat_tags(
except Exception as e:
pass
if not metadata.get("chat_id", "").startswith(
"local:"
): # Only update titles and tags for non-temp chats
if TASKS.TITLE_GENERATION in tasks:
user_message = get_last_user_message(messages)
if user_message and len(user_message) > 100:
user_message = user_message[:100] + "..."
title = None
if tasks[TASKS.TITLE_GENERATION]:
res = await generate_title(
request,
{
"model": message["model"],
@@ -2599,31 +2540,97 @@ async def process_chat_response(
"message", {}
)
tags_string = response_message.get(
"content"
) or response_message.get("reasoning_content", "")
title_string = (
response_message.get("content")
or response_message.get(
"reasoning_content",
)
or message.get("content", user_message)
)
else:
tags_string = ""
title_string = ""
tags_string = tags_string[
tags_string.find("{") : tags_string.rfind("}") + 1
title_string = title_string[
title_string.find("{") : title_string.rfind("}") + 1
]
try:
tags = json.loads(tags_string).get("tags", [])
Chats.update_chat_tags_by_id(
metadata["chat_id"], tags, user
)
await event_emitter(
{
"type": "chat:tags",
"data": tags,
}
title = json.loads(title_string).get(
"title", user_message
)
except Exception as e:
pass
title = ""
if not title:
title = messages[0].get("content", user_message)
Chats.update_chat_title_by_id(metadata["chat_id"], title)
await event_emitter(
{
"type": "chat:title",
"data": title,
}
)
if title == None and len(messages) == 2:
title = messages[0].get("content", user_message)
Chats.update_chat_title_by_id(metadata["chat_id"], title)
await event_emitter(
{
"type": "chat:title",
"data": message.get("content", user_message),
}
)
if TASKS.TAGS_GENERATION in tasks and tasks[TASKS.TAGS_GENERATION]:
res = await generate_chat_tags(
request,
{
"model": message["model"],
"messages": messages,
"chat_id": metadata["chat_id"],
},
user,
)
if res and isinstance(res, dict):
if len(res.get("choices", [])) == 1:
response_message = res.get("choices", [])[0].get(
"message", {}
)
tags_string = response_message.get(
"content"
) or response_message.get("reasoning_content", "")
else:
tags_string = ""
tags_string = tags_string[
tags_string.find("{") : tags_string.rfind("}") + 1
]
try:
tags = json.loads(tags_string).get("tags", [])
Chats.update_chat_tags_by_id(
metadata["chat_id"], tags, user
)
await event_emitter(
{
"type": "chat:tags",
"data": tags,
}
)
except Exception as e:
pass
async def process_chat_response(
request, response, form_data, user, metadata, model, events, tasks
):
event_emitter = None
event_caller = None
if (
@@ -2756,7 +2763,9 @@ async def process_chat_response(
},
)
await background_tasks_handler()
await background_tasks_handler(
request, form_data, user, metadata, tasks
)
if events and isinstance(events, list):
extra_response = {}
@@ -3513,7 +3522,9 @@ async def process_chat_response(
# Normalize usage data to standard format
raw_usage = data.get("usage", {}) or {}
raw_usage.update(data.get("timings", {})) # llama.cpp
raw_usage.update(
data.get("timings", {})
) # llama.cpp
if raw_usage:
usage = normalize_usage(raw_usage)
await event_emitter(
@@ -4346,7 +4357,9 @@ async def process_chat_response(
}
)
await background_tasks_handler()
await background_tasks_handler(
request, form_data, user, metadata, tasks
)
except asyncio.CancelledError:
log.warning("Task was cancelled!")
await event_emitter({"type": "chat:tasks:cancel"})