Dmitry Beresnev commited on
Commit ·
4642f8e
1
Parent(s): f00d814
fix sumarization
Browse files- app/utils/llm_summarizer.py +27 -21
app/utils/llm_summarizer.py
CHANGED
|
@@ -24,13 +24,16 @@ class OpenAICompatSummarizer:
|
|
| 24 |
timeout: Optional[int] = None,
|
| 25 |
max_items_per_request: Optional[int] = None,
|
| 26 |
max_chars_per_item: Optional[int] = None,
|
|
|
|
| 27 |
):
|
| 28 |
self.api_base = (api_base or os.getenv("LLM_API_BASE") or "https://researchengineering-agi.hf.space").rstrip("/")
|
| 29 |
self.api_key = api_key if api_key is not None else os.getenv("LLM_API_KEY", "")
|
| 30 |
self.model = model or os.getenv("LLM_MODEL", "gpt-4o-mini")
|
| 31 |
-
self.timeout = timeout or int(os.getenv("LLM_TIMEOUT", "
|
| 32 |
-
|
| 33 |
-
self.
|
|
|
|
|
|
|
| 34 |
self.enabled = os.getenv("ENABLE_AI_SUMMARIZATION", "true").lower() in {"1", "true", "yes"}
|
| 35 |
self.sleep_seconds = float(os.getenv("LLM_SUMMARY_SLEEP_SECONDS", "0"))
|
| 36 |
|
|
@@ -54,6 +57,8 @@ class OpenAICompatSummarizer:
|
|
| 54 |
chunks = self._chunked(candidates, self.max_items_per_request)
|
| 55 |
for idx, chunk in enumerate(chunks, start=1):
|
| 56 |
texts = [text for _, text in chunk]
|
|
|
|
|
|
|
| 57 |
summaries = self._summarize_chunk(texts, source=source)
|
| 58 |
if not summaries:
|
| 59 |
continue
|
|
@@ -68,25 +73,11 @@ class OpenAICompatSummarizer:
|
|
| 68 |
|
| 69 |
def _build_input_text(self, item: Dict) -> str:
|
| 70 |
title = str(item.get("title", "")).strip()
|
| 71 |
-
summary = str(item.get("summary_raw", item.get("summary", ""))).strip()
|
| 72 |
-
extra = str(item.get("content", item.get("text", item.get("description", "")))).strip()
|
| 73 |
-
|
| 74 |
-
parts = []
|
| 75 |
if title:
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
parts.append(f"Details: {extra}")
|
| 81 |
-
|
| 82 |
-
combined = "\n".join(parts).strip()
|
| 83 |
-
if not combined:
|
| 84 |
-
return ""
|
| 85 |
-
|
| 86 |
-
if len(combined) > self.max_chars_per_item:
|
| 87 |
-
combined = combined[: self.max_chars_per_item].rstrip()
|
| 88 |
-
|
| 89 |
-
return combined
|
| 90 |
|
| 91 |
def _summarize_chunk(self, texts: List[str], source: Optional[str] = None) -> List[str]:
|
| 92 |
system_prompt = (
|
|
@@ -154,3 +145,18 @@ class OpenAICompatSummarizer:
|
|
| 154 |
if size <= 0:
|
| 155 |
return [items]
|
| 156 |
return [items[i : i + size] for i in range(0, len(items), size)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
timeout: Optional[int] = None,
|
| 25 |
max_items_per_request: Optional[int] = None,
|
| 26 |
max_chars_per_item: Optional[int] = None,
|
| 27 |
+
max_chars_total: Optional[int] = None,
|
| 28 |
):
|
| 29 |
self.api_base = (api_base or os.getenv("LLM_API_BASE") or "https://researchengineering-agi.hf.space").rstrip("/")
|
| 30 |
self.api_key = api_key if api_key is not None else os.getenv("LLM_API_KEY", "")
|
| 31 |
self.model = model or os.getenv("LLM_MODEL", "gpt-4o-mini")
|
| 32 |
+
self.timeout = timeout or int(os.getenv("LLM_TIMEOUT", "300"))
|
| 33 |
+
# Conservative defaults to avoid large token bursts on slow servers.
|
| 34 |
+
self.max_items_per_request = max_items_per_request or int(os.getenv("LLM_SUMMARY_BATCH", "2"))
|
| 35 |
+
self.max_chars_per_item = max_chars_per_item or int(os.getenv("LLM_SUMMARY_MAX_CHARS", "600"))
|
| 36 |
+
self.max_chars_total = max_chars_total or int(os.getenv("LLM_SUMMARY_MAX_CHARS_TOTAL", "1200"))
|
| 37 |
self.enabled = os.getenv("ENABLE_AI_SUMMARIZATION", "true").lower() in {"1", "true", "yes"}
|
| 38 |
self.sleep_seconds = float(os.getenv("LLM_SUMMARY_SLEEP_SECONDS", "0"))
|
| 39 |
|
|
|
|
| 57 |
chunks = self._chunked(candidates, self.max_items_per_request)
|
| 58 |
for idx, chunk in enumerate(chunks, start=1):
|
| 59 |
texts = [text for _, text in chunk]
|
| 60 |
+
if self.max_chars_total > 0:
|
| 61 |
+
texts = self._truncate_to_total(texts, self.max_chars_total)
|
| 62 |
summaries = self._summarize_chunk(texts, source=source)
|
| 63 |
if not summaries:
|
| 64 |
continue
|
|
|
|
| 73 |
|
| 74 |
def _build_input_text(self, item: Dict) -> str:
|
| 75 |
title = str(item.get("title", "")).strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
if title:
|
| 77 |
+
if len(title) > self.max_chars_per_item:
|
| 78 |
+
title = title[: self.max_chars_per_item].rstrip()
|
| 79 |
+
return f"Title: {title}"
|
| 80 |
+
return ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
def _summarize_chunk(self, texts: List[str], source: Optional[str] = None) -> List[str]:
|
| 83 |
system_prompt = (
|
|
|
|
| 145 |
if size <= 0:
|
| 146 |
return [items]
|
| 147 |
return [items[i : i + size] for i in range(0, len(items), size)]
|
| 148 |
+
|
| 149 |
+
def _truncate_to_total(self, texts: List[str], max_total: int) -> List[str]:
|
| 150 |
+
if max_total <= 0:
|
| 151 |
+
return texts
|
| 152 |
+
truncated = []
|
| 153 |
+
total = 0
|
| 154 |
+
for text in texts:
|
| 155 |
+
if total >= max_total:
|
| 156 |
+
break
|
| 157 |
+
remaining = max_total - total
|
| 158 |
+
if len(text) > remaining:
|
| 159 |
+
text = text[:remaining].rstrip()
|
| 160 |
+
truncated.append(text)
|
| 161 |
+
total += len(text)
|
| 162 |
+
return truncated
|