From 9e24660c589e2e93a2bfa721787c5b01c595a905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9mence=20Lesn=C3=A9?= Date: Wed, 11 Dec 2024 15:48:47 +0100 Subject: [PATCH] fix: LLM hallucinations answer "content=I understood..." --- app/helpers/call_events.py | 3 +-- app/helpers/call_llm.py | 7 ++----- app/models/message.py | 25 +++++++++++++++++++++++-- 3 files changed, 26 insertions(+), 9 deletions(-) diff --git a/app/helpers/call_events.py b/app/helpers/call_events.py index 8f2f2f8d..e4790222 100644 --- a/app/helpers/call_events.py +++ b/app/helpers/call_events.py @@ -42,7 +42,6 @@ MessageModel, PersonaEnum as MessagePersonaEnum, extract_message_style, - remove_message_action, ) from app.models.next import NextModel from app.models.synthesis import SynthesisModel @@ -636,7 +635,7 @@ def _validate(req: str | None) -> tuple[bool, str | None, str | None]: ) # Delete action and style from the message as they are in the history and LLM hallucinates them - _, content = extract_message_style(remove_message_action(content or "")) + _, content = extract_message_style(content or "") if not content: logger.warning("Error generating SMS report") diff --git a/app/helpers/call_llm.py b/app/helpers/call_llm.py index 9cc7a133..51f01c41 100644 --- a/app/helpers/call_llm.py +++ b/app/helpers/call_llm.py @@ -48,7 +48,6 @@ StyleEnum as MessageStyleEnum, ToolModel as MessageToolModel, extract_message_style, - remove_message_action, ) _db = CONFIG.database.instance() @@ -454,7 +453,7 @@ async def _plugin_tts_callback(text: str) -> None: async def _content_callback(buffer: str) -> None: # Remove tool calls from buffer content and detect style - style, local_content = extract_message_style(remove_message_action(buffer)) + style, local_content = extract_message_style(buffer) await tts_callback(local_content, style) # Build RAG @@ -543,9 +542,7 @@ async def _content_callback(buffer: str) -> None: tool_calls = [tool_call for _, tool_call in tool_calls_buffer.items()] # Delete action and style from the message as they are in the history and LLM hallucinates them - last_style, content_full = extract_message_style( - remove_message_action(content_full) - ) + last_style, content_full = extract_message_style(content_full) logger.debug("Completion response: %s", content_full) logger.debug("Completion tools: %s", tool_calls) diff --git a/app/models/message.py b/app/models/message.py index f1051cc0..842a0c87 100644 --- a/app/models/message.py +++ b/app/models/message.py @@ -163,9 +163,11 @@ def to_openai( return res -def remove_message_action(text: str) -> str: +def _filter_action(text: str) -> str: """ - Remove action from content. AI often adds it by mistake event if explicitly asked not to. + Remove action from content. + + AI often adds it by mistake event if explicitly asked not to. Example: - Input: "action=talk Hello!" @@ -182,6 +184,19 @@ def remove_message_action(text: str) -> str: return text +def _filter_content(text: str) -> str: + """ + Remove content from text. + + AI often adds it by mistake event if explicitly asked not to. + + Example: + - Input: "content=Hello!" + - Output: "Hello!" + """ + return text.replace("content=", "") + + def extract_message_style(text: str) -> tuple[StyleEnum, str]: """ Detect the style of a message and extract it from the text. @@ -190,6 +205,11 @@ def extract_message_style(text: str) -> tuple[StyleEnum, str]: - Input: "style=cheerful Hello!" - Output: (StyleEnum.CHEERFUL, "Hello!") """ + # Apply hallucination filters + text = _filter_action(text) + text = _filter_content(text) + + # Extract style default_style = StyleEnum.NONE res = re.match(_MESSAGE_STYLE_R, text) if not res: @@ -199,6 +219,7 @@ def extract_message_style(text: str) -> tuple[StyleEnum, str]: StyleEnum(res.group(1)), # style (res.group(2) or ""), # content ) + # Regex failed, return original text except ValueError: return default_style, text