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