Repository navigation
fix: [Agent] When adding conversation logs to the knowledge base, the added structural content is empty. - #7738
Conversation
… added structural content is empty.
| problem, _ = Problem.objects.get_or_create(content=problem_text, knowledge_id=knowledge_id) | ||
| problem_paragraph_mapping = ProblemParagraphMapping( | ||
| id=uuid.uuid7(), | ||
| knowledge_id=knowledge_id, |
There was a problem hiding this comment.
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:
continueMinor
uuid.uuid7()— ensure Python version supports it (3.14+ oruuid_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).
fix: [Agent] When adding conversation logs to the knowledge base, the added structural content is empty.