""" title: Memory Filter author: projectmoon author_url: https://git.agnos.is/projectmoon/open-webui-filters version: 0.0.2 required_open_webui_version: 0.3.9 """ # Documentation: https://git.agnos.is/projectmoon/open-webui-filters # # Changelog: # 0.0.1 - Initial release, proof of concept # 0.0.2 - Slightly less hacky (but still hacky) way of getting chat IDs # System imports import asyncio import hashlib import uuid import json from typing import Optional, List, Dict, Callable, Any, NewType, Tuple, Awaitable from typing_extensions import TypedDict, NotRequired # Libraries available to OpenWebUI import markdown from bs4 import BeautifulSoup from pydantic import BaseModel as PydanticBaseModel, Field import chromadb from chromadb import Collection as ChromaCollection from chromadb.api.types import Document as ChromaDocument # OpenWebUI imports from config import CHROMA_CLIENT from apps.rag.main import app from utils.misc import get_last_user_message, get_last_assistant_message from main import generate_chat_completions # OpenWebUI aliases EMBEDDING_FUNCTION = app.state.EMBEDDING_FUNCTION # Custom type declarations EmbeddingFunc = NewType('EmbeddingFunc', Callable[[str], List[Any]]) # Prompts ENRICHMENT_SUMMARY_PROMPT = """ You are tasked with analyzing the following Characters and Plot Details sections and reducing this set of information into lists of the most important points needed for the continuation of the narrative you are writing. Remove duplicate or conflicting information. If there is conflicting information, decide on something consistent and interesting for the story. Your reply must consist of two sections: Characters and Plot Details. These sections must be markdown ### Headers. Under each header, respond with a list of bullet points. Each bullet point must be one piece of relevant information. Limit each bullet point to one sentence. Respond ONLY with the Characters and Plot Details sections, with the bullet points under them, and nothing else. Do not respond with any commentary. ONLY respond with the bullet points. """.replace("\n", " ").strip() QUERY_PROMPT = """ You are tasked with generating questions for a vector database about the narrative presented below. The queries must be questions about parts of the story that you need more details on. The questions must be about past events in the story, or questions about the characters involved or mentioned in the scene (their appearance, mental state, past actions, etc). Your reply must consist of two sections: Characters and Plot Details. These sections must be markdown ### Headers. Under each header, respond with a list of bullet points. Each bullet point must be a single question or sentence that will be given to the vector database. Generate a maximum of 5 Character queries and 5 Plot Detail queries. Limit each bullet point to one sentence. Respond ONLY with the Characters and Plot Details sections, with the bullet points under them, and nothing else. Do not respond with any commentary. ONLY respond with the bullet points. """.replace("\n", " ").strip() SUMMARIZER_PROMPT = """ You are a narrative summarizer. Summarize the given message as if it's part of a story. Your response must have two separate sections: Characters and Plot Details. These sections should be markdown ### Headers. Under each section, respond with a list of bullet points. This knowledge will be stored in a vector database for your future use. The Characters section should note any characters in the scene, and important things that happen to them. Describe the characters' appearances, actions, mental states, and emotional states. The Plot Details section should have a list of important plot details in this scene. The bullet points you generate must be in the context of storing future knowledge about the story. Do not focus on useless details: only focus on information that you could lose in the future as your context window shifts. Limit each bullet point to one sentence. The sentence MUST be in the PAST TENSE. Respond ONLY with the Characters and Plot Details sections, with the bullet points under them, and nothing else. Do not respond with any commentary. ONLY respond with the bullet points. """.replace("\n", " ").strip() class Message(TypedDict): id: NotRequired[str] role: str content: str class MessageInsertMetadata(TypedDict): role: str chapter: str class MessageInsert(TypedDict): message_id: str content: str metadata: MessageInsertMetadata embeddings: List[Any] class BaseModel(PydanticBaseModel): class Config: arbitrary_types_allowed = True class SummarizerResponse(BaseModel): characters: List[str] plot: List[str] class Summarizer(BaseModel): message: str model: str prompt: str = SUMMARIZER_PROMPT def extract_section(self, soup: BeautifulSoup, section_name: str) -> List[str]: for h3 in soup.find_all('h3'): heading = h3.get_text().strip() if heading != section_name: continue # Find the next sibling which should be a