Initial import of Shirobana bot backend
Include utility modules, shared channels, prompts, read-only skills, wardrobe memory and regression tests. Externalize legacy credentials and exclude private runtime state.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
"""Expression guardrails and deterministic receipts; no live API or user data."""
|
||||
from pathlib import Path
|
||||
import sys
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
BASE = Path(__file__).resolve().parents[1]
|
||||
sys.path[:0] = [str(BASE / 'bot-utility'), str(BASE)]
|
||||
import agent_loop
|
||||
from agent import ToolExecutor, ToolContext
|
||||
from chat import engine
|
||||
|
||||
|
||||
class AntiDialogueStyleTests(unittest.IsolatedAsyncioTestCase):
|
||||
def test_all_requested_counterexamples_and_templates_are_explicit(self):
|
||||
prompt = engine.load_instruction('style_instructions.txt')
|
||||
phrases = ['这句话稳', '比之前的都重', '我记下了', '我记得了', '我记住了',
|
||||
'这个账我记住了', '比之前的都轻', '睡吧,我守着', '你去,我跟',
|
||||
'问别人还是问自己', '行,xxx', '什么心思都写着xx上', '这句话接的漂亮',
|
||||
'行,我认', '这句话我不接', 'xx比xx沉', 'xx比xx重', 'xx比xx稳', 'xx比xx轻',
|
||||
'没接你的xxx', '比之前的都强', '他记得这事', '这话我留着', '很平', '稳',
|
||||
'我不拦', '我跟', '回去睡', '你这句话我记着', '认你', '我不催你',
|
||||
'这话是ta告诉你的,还是你自己想明白的', '认下来', '声音没抖,但比刚才稳',
|
||||
'比刚才轻', '比刚才重', '比刚才平', '很直', '这话我记下了', '这话我收下了',
|
||||
'说的比谁都响', '认这个', '收不回去', '认得实', 'xx就是认了', '你自己掂量',
|
||||
'没接你那句xx', '不催', '你掂量']
|
||||
for phrase in phrases:
|
||||
with self.subTest(phrase=phrase): self.assertIn(phrase, prompt)
|
||||
for principle in ('同义改写', '按共同结构识别', '即使历史里的白花曾这样说',
|
||||
'直接谈具体对象', '不是可模仿', '单个汉字全部封禁', '用户既定称呼',
|
||||
'不知道该怎么接', '不要评论自己如何接话'):
|
||||
self.assertIn(principle, prompt)
|
||||
|
||||
def test_builtin_default_is_exactly_the_deployed_expression_file(self):
|
||||
actual = engine.load_instruction('style_instructions.txt')
|
||||
self.assertEqual(actual.strip(), engine.DEFAULT_STYLE_INSTRUCTIONS.strip())
|
||||
self.assertIn('禁用:关系暗语式短应答与话语评断腔', engine.BASE_PROMPT)
|
||||
|
||||
def test_success_fallback_does_not_repeat_memory_acknowledgements(self):
|
||||
result = {'tool':'wardrobe', 'action':'add', 'ok':True,
|
||||
'data':{'item':{'id':'internal-id', 'name':'蓝色短裙', 'description':'不复述的完整细节'}}}
|
||||
output = agent_loop._message_text(agent_loop._fallback_parsed([result]))
|
||||
self.assertIn('蓝色短裙已经在衣柜里', output)
|
||||
for phrase in ('我记', '这话', '我认', '行,', 'internal-id', '不复述的完整细节', '{'):
|
||||
self.assertNotIn(phrase, output)
|
||||
|
||||
def test_polishing_summary_describes_saved_outcome_not_relationship(self):
|
||||
output = agent_loop._polish_facts([{'tool':'wardrobe', 'action':'add', 'ok':True,
|
||||
'data':{'item':{'id':'internal', 'name':'蓝色短裙'}}}])
|
||||
self.assertIn('保存衣物到衣柜', output)
|
||||
self.assertNotIn('记住衣物', output)
|
||||
|
||||
async def test_tool_receipt_is_factual_not_a_memory_performance(self):
|
||||
item = {'id':'123456789abc', 'name':'蓝色短裙', 'category':'短裙', 'description':'白色环绕条纹'}
|
||||
store = SimpleNamespace(add=lambda *args: item)
|
||||
executor = ToolExecutor(artifacts=MagicMock(), modules={'wardrobe':SimpleNamespace(wardrobe=store)})
|
||||
ctx = ToolContext(SimpleNamespace(name='tg'), 'private', 42, 42)
|
||||
result = await executor.execute('wardrobe', {'action':'add','params':{'name':'蓝色短裙'}}, ctx)
|
||||
self.assertTrue(result.ok)
|
||||
self.assertIn('已保存到衣柜', result.safe_message)
|
||||
self.assertNotIn('记住', result.safe_message)
|
||||
self.assertEqual(result.data['item']['description'], '白色环绕条纹')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user