bep40 commited on
Commit
d290ac1
·
verified ·
1 Parent(s): 950be9b

Upload ai_ext.py

Browse files
Files changed (1) hide show
  1. ai_ext.py +83 -1
ai_ext.py CHANGED
@@ -1 +1,83 @@
1
- # placeholder - will be replaced
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """VNEWS AI Extension - rewrite + auto short video generation.
2
+ Imported by app_v2_entry.py to register /api/rewrite_share, /api/topic_post,
3
+ /api/ai_wall, /api/wall, /api/ai/short endpoints on the main FastAPI app.
4
+
5
+ Uses main.py's WALL_FILE (wall_posts.json) for unified data store.
6
+ TTS: edge-tts (HoaiMy female, NamMinh male) with speed control + gTTS fallback.
7
+ """
8
+ import os, re, json, time, random, html as html_lib, subprocess, asyncio
9
+ from urllib.parse import quote_plus, quote, urlparse, urljoin
10
+ from typing import Optional, List, Dict
11
+ import requests
12
+ from bs4 import BeautifulSoup
13
+ from fastapi import Request, Query
14
+ from fastapi.responses import HTMLResponse, JSONResponse, FileResponse
15
+
16
+ from main import app
17
+
18
+ # Import wall store from main.py so we read/write the SAME file
19
+ try:
20
+ from main import _load_wall, _save_wall, _web_context # noqa: F401
21
+ except ImportError:
22
+ _data_dir = "/data" if os.path.isdir("/data") else "/app/data"
23
+ _wall_file = os.path.join(_data_dir, "wall_posts.json")
24
+ def _load_wall():
25
+ try:
26
+ if os.path.exists(_wall_file):
27
+ with open(_wall_file, "r", encoding="utf-8") as f:
28
+ return json.load(f)
29
+ except Exception:
30
+ pass
31
+ return []
32
+ def _save_wall(posts):
33
+ try:
34
+ os.makedirs(os.path.dirname(_wall_file), exist_ok=True)
35
+ tmp = _wall_file + ".tmp"
36
+ with open(tmp, "w", encoding="utf-8") as f:
37
+ json.dump(posts[:100], f, ensure_ascii=False)
38
+ os.replace(tmp, _wall_file)
39
+ except Exception:
40
+ pass
41
+ def _web_context(topic):
42
+ return ""
43
+
44
+ try:
45
+ from huggingface_hub import AsyncInferenceClient
46
+ except Exception:
47
+ AsyncInferenceClient = None
48
+ try:
49
+ from gtts import gTTS
50
+ except Exception:
51
+ gTTS = None
52
+ try:
53
+ from PIL import Image, ImageDraw, ImageFont
54
+ except Exception:
55
+ Image = ImageDraw = ImageFont = None
56
+ try:
57
+ import edge_tts
58
+ except Exception:
59
+ edge_tts = None
60
+
61
+
62
+ def _hf_token():
63
+ for k in ("HF_TOKEN", "HUGGINGFACE_HUB_API_TOKEN", "HUGGING_FACE_HUB_TOKEN", "HF_API_TOKEN"):
64
+ v = os.getenv(k, "").strip()
65
+ if v:
66
+ return v
67
+ return ""
68
+
69
+ HF_TOKEN = _hf_token()
70
+ QWEN_VL_MODEL = os.getenv("QWEN_VL_MODEL", "Qwen/Qwen2.5-VL-7B-Instruct")
71
+ QWEN_TEXT_MODELS = [m.strip() for m in os.getenv(
72
+ "QWEN_TEXT_MODELS",
73
+ "Qwen/Qwen2.5-72B-Instruct,meta-llama/Llama-3.3-70B-Instruct,Qwen/Qwen2.5-7B-Instruct"
74
+ ).split(",") if m.strip()]
75
+ _WORKING_MODEL_TEXT = None
76
+ _WORKING_MODEL_VL = None
77
+ DATA_DIR = "/data" if os.path.isdir("/data") else "/app/data"
78
+ SHORTS_DIR = os.path.join(DATA_DIR, "ai_shorts")
79
+ HEADERS = {
80
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
81
+ "Accept-Language": "vi-VN,vi;q=0.9,en;q=0.8"
82
+ }
83
+ LAST_QWEN_ERROR = ""