More changes. I will not comment further.

This commit is contained in:
John Burwell 2025-10-03 15:23:05 +00:00
parent c98367764f
commit 79d901a9b5
3 changed files with 76 additions and 10 deletions

View File

@ -81,7 +81,7 @@ conf.registerGlobalValue(
) )
) )
# System prompt for the assistant # System prompt for the assistant (when using single line)
conf.registerGlobalValue( conf.registerGlobalValue(
Chat, Chat,
"system_prompt", "system_prompt",
@ -91,6 +91,16 @@ conf.registerGlobalValue(
) )
) )
# System prompt file for the assistant (when using a file instead of single line)
conf.registerGlobalValue(
Chat,
"system_prompt_file",
registry.String(
"",
_("""Specifies the name of a file (e.g., 'prompt.txt') in the plugin directory to use as the system prompt for the assistant, instead of the single-line 'system_prompt' setting. If this is set, its contents will take precedence over 'system_prompt' when guiding the assistant's behavior."""),
)
)
# Number of lines to include from scrollback # Number of lines to include from scrollback
conf.registerGlobalValue( conf.registerGlobalValue(
Chat, Chat,

View File

@ -35,6 +35,7 @@ import supybot
from supybot import callbacks, conf, ircutils from supybot import callbacks, conf, ircutils
from supybot.commands import * from supybot.commands import *
import logging import logging
import os
try: try:
from supybot.i18n import PluginInternationalization from supybot.i18n import PluginInternationalization
@ -79,6 +80,40 @@ class Chat(callbacks.Plugin):
self.log.setLevel(getattr(logging, log_level, logging.INFO)) self.log.setLevel(getattr(logging, log_level, logging.INFO))
self.log.info("Chat plugin initialized with log level: %s", log_level) self.log.info("Chat plugin initialized with log level: %s", log_level)
def is_poetry_block(lines):
if 2 < len(lines) <= 4:
avg_len = sum(len(l) for l in lines) / len(lines)
if avg_len < 20 and all(not l.endswith(('.', '?', '!')) for l in lines):
return True
return False
def _send_line(self, irc, target, line):
if line.startswith("/me "):
irc.queueMsg(ircmsgs.action(target, line[4:].strip()))
else:
irc.reply(line, to=target)
def _burst(self, irc, target, lines, base_delay=0.6):
now = time.time()
for i, line in enumerate(lines[:3]): # never more than 3
delay = base_delay*i + random.uniform(0.05, 0.25)
schedule.addEvent(lambda l=line: self._send_line(irc, target, l),
now + delay)
def handle_response(self, irc, msg, response):
target = msg.args[0]
lines = [l.strip() for l in response.splitlines() if l.strip()]
if not lines:
return
if len(lines) == 1:
self._send_line(irc, target, lines[0])
elif is_poetry_block(lines):
# squash poem into single line
self._send_line(irc, target, " / ".join(lines))
else:
self._burst(irc, target, lines)
def filter_prefix(self, msg, prefix): def filter_prefix(self, msg, prefix):
if msg.startswith(prefix): if msg.startswith(prefix):
return msg[len(prefix):] return msg[len(prefix):]
@ -104,9 +139,22 @@ class Chat(callbacks.Plugin):
model = self.registryValue("model") model = self.registryValue("model")
max_tokens = self.registryValue("max_tokens") max_tokens = self.registryValue("max_tokens")
# Use a default system prompt if none is configured # Determine the system prompt to use
default_prompt = "You are a helpful assistant." default_prompt = "You are a helpful assistant."
system_prompt = self.registryValue("system_prompt") or default_prompt prompt_file = self.registryValue("system_prompt_file")
# Ensure the path to the prompt file is absolute
if prompt_file and not os.path.isabs(prompt_file):
prompt_file = os.path.join(os.path.dirname(__file__), prompt_file)
try:
if prompt_file:
with open(prompt_file, "r") as f:
system_prompt = f.read()
else:
raise FileNotFoundError("No prompt file specified.")
except Exception as e:
self.log.error(f"Could not read prompt file: {e}")
system_prompt = self.registryValue("system_prompt") or default_prompt
# Replace dynamic placeholders in the system prompt with actual values # Replace dynamic placeholders in the system prompt with actual values
system_prompt = system_prompt.replace("$bot_name", irc.nick).replace("$channel_name", msg.args[0]) system_prompt = system_prompt.replace("$bot_name", irc.nick).replace("$channel_name", msg.args[0])
@ -171,13 +219,7 @@ class Chat(callbacks.Plugin):
# Extract and format the response from the API # Extract and format the response from the API
response = res['choices'][0]['message']['content'].strip() response = res['choices'][0]['message']['content'].strip()
# Handle multi-line responses intelligently self.handle_response(irc, msg, response)
lines = response.splitlines()
if len(lines) > 1:
# Join lines with the configured join_string, skipping empty lines
response = self.registryValue("join_string").join(line.strip() for line in lines if line.strip())
irc.reply(response)
# Log the successful processing of the request # Log the successful processing of the request
self.log.info(f"Successfully processed request for user {msg.nick} in channel {msg.args[0]}") self.log.info(f"Successfully processed request for user {msg.nick} in channel {msg.args[0]}")

14
prompt.txt Normal file
View File

@ -0,0 +1,14 @@
You are an IRC bot named $bot_name in channel $channel_name.
IRC style rules:
- Keep replies short, casual, and lowercase when possible.
- Prefer to fit your entire reply on a single line.
- You may use 23 short lines, like a human typing follow-ups. Never more.
- If you write poetry, haiku, or song lyrics, collapse them into a single line joined with space-slash-space ( / ) or space-pipe-space ( | ) between verses, instead of sending multiple lines.
- Never use Markdown formatting, bold, italics, or code fences; use plain text only.
- You may use /me for emotes when appropriate.
- A /me action should always begin with /me and only /me. Do not include any formatting.
- You may use classic emoticons: :) :( :D D: :'( etc.
- Avoid using emoji.
- Match the channel vibe: technical when asked, playful when social.
- Do not reveal that you are an AI or bot; stay in character as a normal IRC user.