fix(rag+tg): mehr Treffer, Pfad-Dedup, keine 4k-Abschneidung

- rag: wide bis 60 Treffer, ES 200, 22 Subqueries, Merge mit Dedup
  pro vollem docnm_kwd (Ordner+Datei getrennt).
- llm: forciertes RAG top_k 60, Tool bis 100k Zeichen.
- telegram: lange Antworten in mehrere Nachrichten (RAG-Listen sichtbar).
This commit is contained in:
Homelab Cursor 2026-03-26 17:15:25 +01:00
parent d17f97f87b
commit 60d0ef671d

View file

@ -130,6 +130,31 @@ CHAT_ID: int | None = None
ACTIVE_LLM_TASKS: dict[int, asyncio.Task] = {}
TG_MSG_LIMIT = 4096
TG_CHUNK = 4000
async def _reply_text_chunked(update: Update, text: str, reply_markup=None) -> None:
t = (text or "")[:250000]
if len(t) <= TG_MSG_LIMIT:
await update.message.reply_text(t, reply_markup=reply_markup)
return
i = 0
part = 0
n = len(t)
while i < n:
part += 1
chunk = t[i : i + TG_CHUNK]
i += TG_CHUNK
is_last = i >= n
body = (f"[Teil {part}] " if part > 1 else "") + chunk
await update.message.reply_text(
body[:TG_MSG_LIMIT],
reply_markup=reply_markup if is_last else None,
)
def _load_token_and_chat():
global CHAT_ID
cfg = config.parse_config()
@ -466,7 +491,7 @@ async def handle_voice(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
memory_client.log_message(session_id, "user", text)
memory_client.log_message(session_id, "assistant", answer)
await update.message.reply_text(answer[:4000], reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
await _reply_text_chunked(update, answer, reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
audio_out = voice.synthesize(answer[:4000])
if audio_out:
@ -515,7 +540,7 @@ async def handle_photo(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
memory_client.log_message(session_id, "user", user_msg)
memory_client.log_message(session_id, "assistant", answer)
await update.message.reply_text(answer[:4000], reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
await _reply_text_chunked(update, answer, reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
except Exception as e:
log.exception("Fehler bei Foto-Analyse")
await update.message.reply_text(f"Fehler bei Bildanalyse: {e}")
@ -691,7 +716,7 @@ async def handle_document(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
memory_client.log_message(session_id, "user", user_msg)
memory_client.log_message(session_id, "assistant", answer)
await update.message.reply_text(answer[:4000], reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
await _reply_text_chunked(update, answer, reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
except Exception as e:
log.exception("Fehler bei Bild-Dokument")
await update.message.reply_text(f"Fehler bei Bildanalyse: {e}")
@ -728,7 +753,7 @@ async def handle_document(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
memory_client.log_message(session_id, "user", user_msg)
memory_client.log_message(session_id, "assistant", answer)
await update.message.reply_text(answer[:4000], reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
await _reply_text_chunked(update, answer, reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
except Exception as e:
log.exception("Fehler bei PDF-Analyse")
await update.message.reply_text(f"Fehler bei PDF: {e}")
@ -856,7 +881,7 @@ async def handle_message(update: Update, ctx: ContextTypes.DEFAULT_TYPE):
suggest = context.last_suggest_result
log.info("suggest_result: type=%s", suggest.get("type"))
await update.message.reply_text(answer[:4000], reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
await _reply_text_chunked(update, answer, reply_markup=build_reply_keyboard(str(update.effective_chat.id)))
except asyncio.CancelledError:
log.info("Freitext-Lauf abgebrochen")
return