From 1f42c015d658d2a19461c45abc76e8b655c57e08 Mon Sep 17 00:00:00 2001
From: ValueOn AG
Date: Sat, 28 Mar 2026 22:29:15 +0100
Subject: [PATCH] fixes commcoach
---
.../features/commcoach/serviceCommcoach.py | 52 ++++++++++++++++++-
.../features/commcoach/serviceCommcoachAi.py | 16 ++++--
2 files changed, 61 insertions(+), 7 deletions(-)
diff --git a/modules/features/commcoach/serviceCommcoach.py b/modules/features/commcoach/serviceCommcoach.py
index 36fc6e16..5e5aa810 100644
--- a/modules/features/commcoach/serviceCommcoach.py
+++ b/modules/features/commcoach/serviceCommcoach.py
@@ -33,6 +33,7 @@ from .serviceCommcoachContextRetrieval import (
buildSessionSummariesForPrompt,
findSessionByDate,
searchSessionsByTopic,
+ searchSessionsByTopicRag,
_parseDateFromMessage,
PREVIOUS_SESSION_SUMMARIES_COUNT,
ROLLING_OVERVIEW_SESSION_THRESHOLD,
@@ -1035,10 +1036,29 @@ class CommcoachService:
result["rollingOverview"] = rollingOverview
elif intent == RetrievalIntent.RECALL_TOPIC:
- retrieved = searchSessionsByTopic(completedSessions, userContent)
+ retrieved = list(searchSessionsByTopic(completedSessions, userContent))
+ queryVector = await self._embedUserQuery(userContent)
+ if queryVector:
+ ragHits = searchSessionsByTopicRag(
+ userContent,
+ self.userId,
+ self.instanceId,
+ mandateId=self.mandateId,
+ queryVector=queryVector,
+ )
+ for hit in ragHits:
+ content = (hit.get("content") or "").strip()
+ if not content:
+ continue
+ retrieved.append({
+ "summary": content[:450],
+ "date": "",
+ "source": "rag",
+ "ragSourceLabel": hit.get("fileName") or "Mandantenwissen",
+ })
result["retrievedByTopic"] = retrieved
if retrieved:
- logger.info(f"Topic recall: found {len(retrieved)} sessions for query")
+ logger.info(f"Topic recall: {len(retrieved)} item(s) (sessions + optional RAG)")
result["previousSessionSummaries"] = buildSessionSummariesForPrompt(
allSessions, excludeSessionId=sessionId, limit=PREVIOUS_SESSION_SUMMARIES_COUNT
)
@@ -1101,3 +1121,31 @@ class CommcoachService:
)
)
return await aiService.callAi(aiRequest)
+
+ async def _embedUserQuery(self, text: str) -> Optional[List[float]]:
+ """Embedding for mandate-wide RAG (same ServiceCenter AI service as coaching calls)."""
+ snippet = (text or "").strip()[:2000]
+ if not snippet:
+ return None
+ from modules.serviceCenter import getService
+ from modules.serviceCenter.context import ServiceCenterContext
+
+ serviceContext = ServiceCenterContext(
+ user=self.currentUser,
+ mandate_id=self.mandateId,
+ feature_instance_id=self.instanceId,
+ )
+ aiService = getService("ai", serviceContext)
+ await aiService.ensureAiObjectsInitialized()
+ try:
+ response = await aiService.callEmbedding([snippet])
+ except Exception as e:
+ logger.warning(f"CommCoach RAG embedding failed: {e}")
+ return None
+ if not response or response.errorCount > 0:
+ return None
+ embs = (response.metadata or {}).get("embeddings") or []
+ vec = embs[0] if embs else None
+ if isinstance(vec, list) and len(vec) > 0:
+ return vec
+ return None
diff --git a/modules/features/commcoach/serviceCommcoachAi.py b/modules/features/commcoach/serviceCommcoachAi.py
index 7ba52f58..97deb373 100644
--- a/modules/features/commcoach/serviceCommcoachAi.py
+++ b/modules/features/commcoach/serviceCommcoachAi.py
@@ -229,12 +229,18 @@ WICHTIG: Antworte NUR mit dem JSON-Objekt. Kein Text vor oder nach dem JSON."""
prompt += f"\n{retrievedSession.get('summary', '')[:500]}"
if retrievedByTopic:
- prompt += "\n\nRelevante Sessions zum angefragten Thema:"
- for s in retrievedByTopic[:3]:
- summary = s.get("summary", "")
+ prompt += "\n\nRelevante Sessions und Mandantenwissen zum angefragten Thema:"
+ for s in retrievedByTopic[:5]:
+ summary = s.get("summary", s.get("content", ""))
+ if not summary:
+ continue
dateStr = s.get("date", "")
- if summary:
- prompt += f"\n- [{dateStr}] {summary[:300]}"
+ if s.get("source") == "rag":
+ label = s.get("ragSourceLabel") or "Mandantenwissen"
+ prompt += f"\n- [Wissen: {label}] {summary[:320]}"
+ else:
+ prefix = f"[{dateStr}] " if dateStr else ""
+ prompt += f"\n- {prefix}{summary[:300]}"
if openTasks:
prompt += "\n\nOffene Aufgaben:"