Compare commits
2 Commits
efe7f901c2
...
3d252ee729
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d252ee729 | |||
| b918ba51a8 |
@@ -103,6 +103,15 @@ class SentimentCog(commands.Cog):
|
|||||||
or f"<@!{self.bot.user.id}>" in (message.content or "")
|
or f"<@!{self.bot.user.id}>" in (message.content or "")
|
||||||
)
|
)
|
||||||
if bot_mentioned_in_text:
|
if bot_mentioned_in_text:
|
||||||
|
# Classify intent: only run expensive mention scan for reports,
|
||||||
|
# let ChatCog handle casual chat/questions
|
||||||
|
intent = await self.bot.llm.classify_mention_intent(
|
||||||
|
message.content or ""
|
||||||
|
)
|
||||||
|
logger.info(
|
||||||
|
"Mention intent for %s: %s", message.author, intent
|
||||||
|
)
|
||||||
|
if intent == "report":
|
||||||
mention_config = config.get("mention_scan", {})
|
mention_config = config.get("mention_scan", {})
|
||||||
if mention_config.get("enabled", True):
|
if mention_config.get("enabled", True):
|
||||||
await self._maybe_start_mention_scan(message, mention_config)
|
await self._maybe_start_mention_scan(message, mention_config)
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ async def main():
|
|||||||
print("Database not available.")
|
print("Database not available.")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# Use escalation model for better profile generation
|
||||||
llm = LLMClient(
|
llm = LLMClient(
|
||||||
base_url=os.getenv("LLM_BASE_URL", ""),
|
base_url=os.getenv("LLM_ESCALATION_BASE_URL", os.getenv("LLM_BASE_URL", "")),
|
||||||
model=os.getenv("LLM_MODEL", "gpt-4o-mini"),
|
model=os.getenv("LLM_ESCALATION_MODEL", os.getenv("LLM_MODEL", "gpt-4o-mini")),
|
||||||
api_key=os.getenv("LLM_API_KEY", "not-needed"),
|
api_key=os.getenv("LLM_ESCALATION_API_KEY", os.getenv("LLM_API_KEY", "not-needed")),
|
||||||
)
|
)
|
||||||
|
|
||||||
states = await db.load_all_user_states()
|
states = await db.load_all_user_states()
|
||||||
@@ -52,8 +53,18 @@ async def main():
|
|||||||
current_profile="",
|
current_profile="",
|
||||||
)
|
)
|
||||||
|
|
||||||
if result and result.get("profile_update"):
|
if not result:
|
||||||
profile = result["profile_update"]
|
print(f" LLM returned no result, keeping existing notes.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Use profile_update if provided, otherwise build from permanent memories
|
||||||
|
profile = result.get("profile_update")
|
||||||
|
if not profile:
|
||||||
|
permanent = [m["memory"] for m in result.get("memories", []) if m.get("expiration") == "permanent"]
|
||||||
|
if permanent:
|
||||||
|
profile = " ".join(permanent)
|
||||||
|
|
||||||
|
if profile:
|
||||||
print(f" New: {profile[:200]}")
|
print(f" New: {profile[:200]}")
|
||||||
await db.save_user_state(
|
await db.save_user_state(
|
||||||
user_id=state["user_id"],
|
user_id=state["user_id"],
|
||||||
|
|||||||
@@ -675,6 +675,49 @@ class LLMClient:
|
|||||||
self._log_llm("chat", elapsed, False, req_json, error=str(e))
|
self._log_llm("chat", elapsed, False, req_json, error=str(e))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
async def classify_mention_intent(self, message_text: str) -> str:
|
||||||
|
"""Classify whether a bot @mention is a chat/question or a moderation report.
|
||||||
|
|
||||||
|
Returns 'chat' or 'report'. Defaults to 'chat' on failure.
|
||||||
|
"""
|
||||||
|
prompt = (
|
||||||
|
"You are classifying the intent of a Discord message that @mentioned a bot.\n"
|
||||||
|
"Reply with EXACTLY one word: 'chat' or 'report'.\n\n"
|
||||||
|
"- 'chat' = the user is talking to the bot, asking a question, joking, greeting, "
|
||||||
|
"or having a conversation. This includes things like 'what do you think?', "
|
||||||
|
"'hey bot', 'do you know...', or any general interaction.\n"
|
||||||
|
"- 'report' = the user is flagging bad behavior, asking the bot to check/scan "
|
||||||
|
"the chat, reporting toxicity, or pointing out someone being problematic. "
|
||||||
|
"This includes things like 'check this', 'they're being toxic', 'look at what "
|
||||||
|
"they said', 'scan the chat', or concerns about other users.\n\n"
|
||||||
|
"If unsure, say 'chat'."
|
||||||
|
)
|
||||||
|
t0 = time.monotonic()
|
||||||
|
|
||||||
|
async with self._semaphore:
|
||||||
|
try:
|
||||||
|
temp_kwargs = {"temperature": 0.0} if self._supports_temperature else {}
|
||||||
|
response = await self._client.chat.completions.create(
|
||||||
|
model=self.model,
|
||||||
|
messages=[
|
||||||
|
{"role": "system", "content": prompt},
|
||||||
|
{"role": "user", "content": message_text},
|
||||||
|
],
|
||||||
|
**temp_kwargs,
|
||||||
|
max_completion_tokens=16,
|
||||||
|
)
|
||||||
|
elapsed = int((time.monotonic() - t0) * 1000)
|
||||||
|
content = (response.choices[0].message.content or "").strip().lower()
|
||||||
|
intent = "report" if "report" in content else "chat"
|
||||||
|
self._log_llm("classify_intent", elapsed, True, message_text[:200], intent)
|
||||||
|
logger.info("Mention intent classified as '%s' for: %s", intent, message_text[:80])
|
||||||
|
return intent
|
||||||
|
except Exception as e:
|
||||||
|
elapsed = int((time.monotonic() - t0) * 1000)
|
||||||
|
logger.error("Intent classification error: %s", e)
|
||||||
|
self._log_llm("classify_intent", elapsed, False, message_text[:200], error=str(e))
|
||||||
|
return "chat"
|
||||||
|
|
||||||
async def extract_memories(
|
async def extract_memories(
|
||||||
self,
|
self,
|
||||||
conversation: list[dict[str, str]],
|
conversation: list[dict[str, str]],
|
||||||
|
|||||||
Reference in New Issue
Block a user