Spaces:
Running
Running
Upload app_v2_entry.py with huggingface_hub
Browse files- app_v2_entry.py +73 -35
app_v2_entry.py
CHANGED
|
@@ -1671,54 +1671,92 @@ async def api_personal_post_preview(request: Request):
|
|
| 1671 |
# Try to parse the ---SLIDE--- format
|
| 1672 |
pattern = r'---SLIDE\s*(\d+)---\s*\n(.*?)(?=---SLIDE|\Z)'
|
| 1673 |
matches = re.findall(pattern, ai_text, re.DOTALL)
|
|
|
|
| 1674 |
if matches:
|
| 1675 |
for idx, (num, content) in enumerate(matches):
|
| 1676 |
# Normalize: ensure complete sentences
|
| 1677 |
text = _ensure_sentence_complete(content)
|
| 1678 |
-
if len(text) >
|
| 1679 |
img = source_images[idx] if idx < len(source_images) else ""
|
| 1680 |
slides.append({"text": text, "image": img, "index": idx + 1})
|
| 1681 |
|
| 1682 |
-
#
|
| 1683 |
if len(slides) < 3:
|
| 1684 |
-
|
| 1685 |
-
|
| 1686 |
-
|
| 1687 |
-
|
| 1688 |
-
|
| 1689 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1690 |
continue
|
| 1691 |
-
|
| 1692 |
-
|
| 1693 |
-
|
| 1694 |
-
|
| 1695 |
-
|
| 1696 |
-
|
| 1697 |
-
if para_count >= 6:
|
| 1698 |
break
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1699 |
|
|
|
|
| 1700 |
if len(slides) < 2:
|
| 1701 |
-
|
| 1702 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1703 |
if ai_text:
|
| 1704 |
-
# Split by sentences for better chunks
|
| 1705 |
sentences = re.split(r'(?<=[.!?])\s+', ai_text)
|
| 1706 |
-
|
| 1707 |
-
|
| 1708 |
-
|
| 1709 |
-
|
| 1710 |
-
|
| 1711 |
-
|
| 1712 |
-
|
| 1713 |
-
|
| 1714 |
-
|
| 1715 |
-
|
| 1716 |
-
|
| 1717 |
-
|
| 1718 |
-
|
| 1719 |
-
|
| 1720 |
-
|
| 1721 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1722 |
|
| 1723 |
preview = {
|
| 1724 |
"title": title,
|
|
@@ -1726,7 +1764,7 @@ async def api_personal_post_preview(request: Request):
|
|
| 1726 |
"opinion": opinion,
|
| 1727 |
"images": source_images[:10],
|
| 1728 |
"sources": source_details[:5],
|
| 1729 |
-
"slides": slides
|
| 1730 |
}
|
| 1731 |
|
| 1732 |
return JSONResponse({"preview": preview})
|
|
|
|
| 1671 |
# Try to parse the ---SLIDE--- format
|
| 1672 |
pattern = r'---SLIDE\s*(\d+)---\s*\n(.*?)(?=---SLIDE|\Z)'
|
| 1673 |
matches = re.findall(pattern, ai_text, re.DOTALL)
|
| 1674 |
+
|
| 1675 |
if matches:
|
| 1676 |
for idx, (num, content) in enumerate(matches):
|
| 1677 |
# Normalize: ensure complete sentences
|
| 1678 |
text = _ensure_sentence_complete(content)
|
| 1679 |
+
if len(text) > 40:
|
| 1680 |
img = source_images[idx] if idx < len(source_images) else ""
|
| 1681 |
slides.append({"text": text, "image": img, "index": idx + 1})
|
| 1682 |
|
| 1683 |
+
# If we have parsed slides, ensure minimum 3
|
| 1684 |
if len(slides) < 3:
|
| 1685 |
+
# Use parsed slides as base, fill remaining from AI text
|
| 1686 |
+
used_indices = set()
|
| 1687 |
+
for s in slides:
|
| 1688 |
+
used_indices.add(s['index'] - 1)
|
| 1689 |
+
|
| 1690 |
+
# Split remaining AI text into more slides
|
| 1691 |
+
sentences = re.split(r'(?<=[.!?])\s+', ai_text)
|
| 1692 |
+
current_chunk = ""
|
| 1693 |
+
next_idx = len(slides)
|
| 1694 |
+
|
| 1695 |
+
for sent in sentences:
|
| 1696 |
+
sent = _ensure_sentence_complete(sent)
|
| 1697 |
+
if len(sent) < 20:
|
| 1698 |
continue
|
| 1699 |
+
|
| 1700 |
+
# Skip if this sentence is already in parsed slides
|
| 1701 |
+
found = False
|
| 1702 |
+
for slide in slides:
|
| 1703 |
+
if sent[:50] in slide['text']:
|
| 1704 |
+
found = True
|
|
|
|
| 1705 |
break
|
| 1706 |
+
|
| 1707 |
+
if found:
|
| 1708 |
+
continue
|
| 1709 |
+
|
| 1710 |
+
if current_chunk and len(current_chunk + " " + sent) <= 380:
|
| 1711 |
+
current_chunk += " " + sent
|
| 1712 |
+
else:
|
| 1713 |
+
if len(current_chunk) > 50:
|
| 1714 |
+
img = source_images[next_idx] if next_idx < len(source_images) else ""
|
| 1715 |
+
slides.append({"text": current_chunk, "image": img, "index": next_idx + 1})
|
| 1716 |
+
current_chunk = sent
|
| 1717 |
+
next_idx += 1
|
| 1718 |
+
|
| 1719 |
+
# Add final chunk
|
| 1720 |
+
if len(current_chunk) > 50 and next_idx < 6:
|
| 1721 |
+
img = source_images[next_idx] if next_idx < len(source_images) else ""
|
| 1722 |
+
slides.append({"text": current_chunk, "image": img, "index": next_idx + 1})
|
| 1723 |
|
| 1724 |
+
# Ultimate fallback: create slides from opinion + source
|
| 1725 |
if len(slides) < 2:
|
| 1726 |
+
slides = []
|
| 1727 |
+
# Slide 1: opinion
|
| 1728 |
+
if opinion and len(opinion) > 20:
|
| 1729 |
+
slides.append({"text": opinion[:450], "image": source_images[0] if source_images else "", "index": 1})
|
| 1730 |
+
|
| 1731 |
+
# Slide 2-6: from AI text or sources
|
| 1732 |
if ai_text:
|
|
|
|
| 1733 |
sentences = re.split(r'(?<=[.!?])\s+', ai_text)
|
| 1734 |
+
for i, sent in enumerate(sentences[:5]):
|
| 1735 |
+
text = _ensure_sentence_complete(_clean(sent))
|
| 1736 |
+
if len(text) > 60:
|
| 1737 |
+
if len(slides) < 6:
|
| 1738 |
+
img = source_images[len(slides)] if len(slides) < len(source_images) else ""
|
| 1739 |
+
slides.append({"text": text, "image": img, "index": len(slides) + 1})
|
| 1740 |
+
|
| 1741 |
+
# Fill remaining with key points from sources
|
| 1742 |
+
src_idx = len(slides)
|
| 1743 |
+
while len(slides) < 4 and src_idx < len(source_details):
|
| 1744 |
+
paragraphs = source_details[src_idx].get("paragraphs", [])
|
| 1745 |
+
for p in paragraphs[:2]:
|
| 1746 |
+
if len(p) > 60 and len(slides) < 6:
|
| 1747 |
+
img = source_images[len(slides)] if len(slides) < len(source_images) else ""
|
| 1748 |
+
slides.append({"text": _ensure_sentence_complete(p[:400]), "image": img, "index": len(slides) + 1})
|
| 1749 |
+
src_idx += 1
|
| 1750 |
+
|
| 1751 |
+
# Final fallback: ensure at least 2-3 slides
|
| 1752 |
+
while len(slides) < 3:
|
| 1753 |
+
idx = len(slides)
|
| 1754 |
+
if idx == 0 and opinion:
|
| 1755 |
+
slides.append({"text": opinion[:400], "image": "", "index": 1})
|
| 1756 |
+
elif ai_text:
|
| 1757 |
+
slides.append({"text": ai_text[idx*300:(idx+1)*300], "image": "", "index": idx + 1})
|
| 1758 |
+
else:
|
| 1759 |
+
slides.append({"text": f"Nguồn tham khảo {idx + 1}", "image": "", "index": idx + 1})
|
| 1760 |
|
| 1761 |
preview = {
|
| 1762 |
"title": title,
|
|
|
|
| 1764 |
"opinion": opinion,
|
| 1765 |
"images": source_images[:10],
|
| 1766 |
"sources": source_details[:5],
|
| 1767 |
+
"slides": slides[:6] # Max 6 slides
|
| 1768 |
}
|
| 1769 |
|
| 1770 |
return JSONResponse({"preview": preview})
|