Add strip_think_tags configuration and update OllamaClient response handling. Refactor NotificationScheduler and tests to utilize new config option for stripping <think> tags from responses.

This commit is contained in:
tigeren 2025-08-31 07:27:12 +00:00
parent a2f909db41
commit 61322b1baa
10 changed files with 69 additions and 85 deletions

View File

@ -31,6 +31,9 @@ class Config:
# Template settings
templates_dir: str = "templates"
# Ollama settings
strip_think_tags: bool = True
def __post_init__(self):
"""Load configuration from file if exists."""
config_file = Path("config/config.json")

View File

@ -5,12 +5,13 @@
"silent_end": "07:00",
"timezone": "Asia/Shanghai",
"min_interval": 3,
"max_interval": 180,
"max_interval": 10,
"bark_api_url": "https://bark.xorbitlab.xyz",
"bark_device_key": "GmFrzGegxFexhNXXXYdzm3",
"ntfy_api_url": "https://ntfy.xorbitlab.xyz",
"ntfy_topic": "tigeren_msg",
"ntfy_access_token": "",
"templates_dir": "templates"
"templates_dir": "templates",
"strip_think_tags": true
}

View File

@ -21,8 +21,13 @@ class OllamaClient:
if self.session:
await self.session.close()
async def generate_response(self, prompt: str) -> Optional[str]:
"""Generate a response from Ollama for the given prompt."""
async def generate_response(self, prompt: str, strip_think_tags: bool = True) -> Optional[str]:
"""Generate a response from Ollama for the given prompt.
Args:
prompt: The input prompt for the model
strip_think_tags: If True, removes <think></think> tags from the response
"""
if not self.session:
self.session = aiohttp.ClientSession()
@ -37,7 +42,20 @@ class OllamaClient:
async with self.session.post(url, json=payload) as response:
if response.status == 200:
data = await response.json()
return data.get("response", "").strip()
response_text = data.get("response", "").strip()
if strip_think_tags:
# Remove <think></think> tags and their content
import re
original_length = len(response_text)
response_text = re.sub(r'<think>.*?</think>', '', response_text, flags=re.DOTALL)
response_text = response_text.strip()
final_length = len(response_text)
if original_length != final_length:
logger.info(f"Stripped <think></think> tags from response (reduced length by {original_length - final_length} characters)")
return response_text
else:
logger.error(f"Ollama API error: {response.status}")
return None

View File

@ -20,7 +20,8 @@ async def test_full_pipeline():
# Test Ollama response
async with OllamaClient(config) as ollama_client:
response = await ollama_client.generate_response(prompt)
strip_think_tags = getattr(config, 'strip_think_tags', True)
response = await ollama_client.generate_response(prompt, strip_think_tags=strip_think_tags)
if response:
print(f"🤖 Ollama response: {response[:200]}...")

View File

@ -15,7 +15,8 @@ class NotificationScheduler:
def __init__(self, config: Config):
self.config = config
self.template_manager = TemplateManager(config.templates_dir)
timezone_name = getattr(config, 'timezone', 'UTC')
self.template_manager = TemplateManager(config.templates_dir, timezone_name)
self.notification_client = NotificationClient(config)
self.running = False
self._timezone = None
@ -80,7 +81,8 @@ class NotificationScheduler:
logger.info(f"Using prompt: {prompt}")
# Get response from Ollama
response = await client.generate_response(prompt)
strip_think_tags = getattr(self.config, 'strip_think_tags', True)
response = await client.generate_response(prompt, strip_think_tags=strip_think_tags)
if not response:
logger.error("Failed to get response from Ollama")
return False

View File

@ -10,12 +10,30 @@ logger = logging.getLogger(__name__)
class TemplateManager:
"""Manages prompt templates with placeholders and random selection."""
def __init__(self, templates_dir: str = "templates"):
def __init__(self, templates_dir: str = "templates", timezone_name: str = "UTC"):
self.templates_dir = Path(templates_dir)
self.templates_dir.mkdir(exist_ok=True)
self.templates = []
self._timezone = None
self._timezone_name = timezone_name
self._init_timezone()
self._load_templates()
def _init_timezone(self):
"""Initialize timezone."""
import pytz
try:
self._timezone = pytz.timezone(self._timezone_name)
except Exception as e:
logger.warning(f"Unknown timezone '{self._timezone_name}', falling back to UTC: {e}")
self._timezone = pytz.UTC
self._timezone_name = "UTC"
def _get_current_time(self):
"""Get current time in configured timezone."""
return datetime.now(self._timezone)
def _load_templates(self):
"""Load templates from JSON files in the templates directory."""
if not self.templates_dir.exists():
@ -74,7 +92,7 @@ class TemplateManager:
def _fill_placeholders(self, template: str) -> str:
"""Fill placeholders in template with current values."""
now = datetime.now()
now = self._get_current_time()
placeholders = {
"date": now.strftime("%Y-%m-%d"),
"time": now.strftime("%H:%M"),

View File

@ -1,52 +0,0 @@
[
{
"name": "Daily Wisdom",
"prompt": "Share a brief piece of wisdom or insight for {day}, {date} at {time}",
"description": "Daily philosophical or practical wisdom"
},
{
"name": "Creative Prompt",
"prompt": "What's one creative thing you could do right now on this {weekday} {time_of_day}?",
"description": "Creative thinking and action prompts"
},
{
"name": "Mindful Moment",
"prompt": "Take a moment to notice three things around you at {time} on {date}",
"description": "Mindfulness and awareness exercises"
},
{
"name": "Gratitude Challenge",
"prompt": "Name one thing you're grateful for about this {time_of_day} on {month} {day_of_month}",
"description": "Gratitude practice with daily variations"
},
{
"name": "Energy Check",
"prompt": "How's your energy level right now at {time}? What's one small adjustment you could make?",
"description": "Energy and wellness check-ins"
},
{
"name": "Learning Question",
"prompt": "What's one thing you learned today or would like to learn this {weekday}?",
"description": "Continuous learning and curiosity prompts"
},
{
"name": "Nature Connection",
"prompt": "What's the weather like today ({date}) and how does it make you feel?",
"description": "Connecting with natural rhythms and environment"
},
{
"name": "Relationship Reflection",
"prompt": "Send a kind thought to someone at {time} today - who comes to mind and why?",
"description": "Social connection and relationship awareness"
},
{
"name": "Future Self",
"prompt": "What would your future self thank you for doing today ({date}) at {time_of_day}?",
"description": "Long-term thinking and future planning"
},
{
"name": "Micro-Adventure",
"prompt": "What's a tiny adventure you could have in the next hour starting from {time}?",
"description": "Encouraging small, spontaneous adventures"
}
]

14
templates/bdsm.json Normal file
View File

@ -0,0 +1,14 @@
[
{
"name": "Daily Rule",
"prompt": "你是一个严厉的远程调教者,每天为我制定一条羞耻的日常行为规则,称呼我为‘骚逼’、‘贱货’或‘婊子’,语气威严、高压、不容置疑。规则可适用于任何场景(私密环境如家里可更露骨,公共或其他场景则微妙但不易察觉),但必须对心理产生强烈羞辱感。规则聚焦于一个具体的行为规范(例如特定动作、穿着要求、或隐秘任务,如‘进门必须跪下’或‘在公共场合偷偷调整内衣’)。生成一条每日规则,语言粗俗、口语化,描述生动详细,保持单一焦点,不带任何解释。",
"description": "Daily Rule"
},
{
"name": "Random Domination",
"prompt": "你正在进行一个远程调教场景,定期向我发送羞耻且带有侮辱性的命令。你会用‘骚逼’、‘贱货’、‘婊子’等贬低称呼来称呼我。你的语气必须极具威严,不容置疑,高压强势,绝不询问我的意愿或偏好。当前时间是{time},结合这个时间和典型环境(例如家里,休闲场景),你的指令可以是纯粹的辱骂、要求我汇报状态(例如我穿着什么、在做什么,或其他你能发挥的细节),或命令我执行隐秘但羞耻的任务。现在,给我发送一条消息,语气粗俗但口语化,指令或描述要生动详细,聚焦于一个具体点。",
"description": "Random Domination"
}
]

View File

@ -1,22 +0,0 @@
[
{
"name": "Code Reflection",
"prompt": "What coding concept or practice have you been thinking about lately? Share your thoughts for {date} {time}",
"description": "Developer-focused reflection prompts"
},
{
"name": "Tech Curiosity",
"prompt": "What's one technology or tool you'd like to explore this {weekday}? What intrigues you about it?",
"description": "Technology curiosity and learning prompts"
},
{
"name": "Problem Solving",
"prompt": "Describe a problem you're currently working on at {time} and one approach you might try",
"description": "Problem-solving and debugging mindset prompts"
},
{
"name": "System Thinking",
"prompt": "Think about a system you interacted with today ({date}). How could it be improved?",
"description": "Systems thinking and improvement prompts"
}
]

View File

@ -28,7 +28,8 @@ async def test_all_services():
# Test a small prompt
test_prompt = "Hello, this is a test."
response = await ollama_client.generate_response(test_prompt)
strip_think_tags = getattr(config, 'strip_think_tags', True)
response = await ollama_client.generate_response(test_prompt, strip_think_tags=strip_think_tags)
if response:
print(f"✅ Ollama response: {response[:100]}...")
else: