Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions apps/application/serializers/application_chat_record.py
Original file line number Diff line number Diff line change
Expand Up @@ -393,15 +393,17 @@ def post_improve(self, instance: Dict, request=None, scope="WORKSPACE", with_val
paragraph_ids = []
problem_paragraph_mappings = []
for chat_record in chat_record_list:
answer_text = "".join([r.get("content") for r in chat_record.messages if r.get("type") == "TEXT"])
problem_text = chat_record.question.get("content")
paragraph = Paragraph(
id=uuid.uuid7(),
document_id=document_id,
content=chat_record.answer_text,
content=answer_text,
knowledge_id=knowledge_id,
title=chat_record.problem_text,
chunks=text_to_chunk(chat_record.answer_text),
title=problem_text,
chunks=text_to_chunk(answer_text),
)
problem, _ = Problem.objects.get_or_create(content=chat_record.problem_text, knowledge_id=knowledge_id)
problem, _ = Problem.objects.get_or_create(content=problem_text, knowledge_id=knowledge_id)
problem_paragraph_mapping = ProblemParagraphMapping(
id=uuid.uuid7(),
knowledge_id=knowledge_id,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a review of the changes:

Potential Issues

1. get("content") may return None → TypeError in join

answer_text = "".join([r.get("content") for r in chat_record.messages if r.get("type") == "TEXT"])

If any matching message has no "content" key (or it's None), str.join raises TypeError: sequence item N: expected str instance, NoneType found.

Fix:

answer_text = "".join(r.get("content") or "" for r in chat_record.messages if r.get("type") == "TEXT")

2. Accessing messages without guard

If chat_record is a model instance from an older DB record lacking messages, or if it's None, this will fail. Consider defensive handling:

messages = getattr(chat_record, "messages", None) or []

3. Type inconsistency risk with problem_text

chat_record.question.get("content") — if question is None or not a dict, .get fails. Also unclear whether "content" can be None. You may want a .strip() / fallback for title integrity.

4. Behavior change / backward compatibility

Previously used chat_record.answer_text and chat_record.problem_text. If those are denormalized fields that some legacy records still rely on (and messages/question are nullable), this change could produce empty content/title on older rows. Verify a migration/backfill path exists.

5. Multiple TEXT messages concatenated without separator

"".join(...) concatenates raw strings. If messages carry paragraphs or need separators (e.g., "\n"), you'll merge words. Confirm the intended semantics:

"\n".join(...)

Optimization Suggestions

1. Avoid list-then-join; use generator

answer_text = "".join(
    r.get("content") or ""
    for r in chat_record.messages
    if r.get("type") == "TEXT"
)

2. Compute text_to_chunk(answer_text) once

Currently called once — good — but consider extracting into a local to avoid accidental duplication in future edits.

3. Batch get_or_create for Problems

In a loop, each Problem.objects.get_or_create(...) hits the DB. For large batches, prefetch existing problems first:

existing = {p.content: p for p in Problem.objects.filter(knowledge_id=knowledge_id, content__in=[...])}

Then create missing ones in bulk.

4. Consider bulk_create for Paragraph and ProblemParagraphMapping

Inside a for loop over chat_record_list, all inserts are per-row. For performance at scale, accumulate into lists and bulk_create(..., batch_size=...) outside the loop.

5. Consistency of text extraction

Extracting text logic (join TEXT messages) is now inline. If used elsewhere (e.g., a chat_record.answer_text property previously), consider centralizing as a helper/property to keep behavior uniform across the codebase.

6. Empty-string edge case

If answer_text is "" (no TEXT messages), you'll create a Paragraph with empty content and empty chunks. Decide whether to skip such records:

if not answer_text:
    continue

Minor

  • uuid.uuid7() — ensure Python version supports it (3.14+ or uuid_utils). Not caused by this diff, but worth verifying against your runtime.
  • The diff line count header (@@ -393,15 +393,17 @@) suggests added lines; confirm indentation consistency (the snippet looks fine).

Expand Down
Loading