liumaolin commited on
Commit
aac52b6
·
1 Parent(s): f7b034a

Add unit tests for LLM dialogue with configurable chat history

Browse files

- Introduce `TestLLMDialogue` for testing LLM conversational behavior.
- Implement multi-turn dialogue tests with logical Chinese and English prompts.
- Mock configurable history management using `RunnableWithMessageHistory`.

Files changed (1) hide show
  1. tests/test_llm_dialogue.py +112 -0
tests/test_llm_dialogue.py ADDED
@@ -0,0 +1,112 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import unittest
2
+
3
+ from langchain.chains.conversation.memory import ConversationBufferWindowMemory
4
+ from langchain_community.chat_models.llamacpp import ChatLlamaCpp
5
+ from langchain_core.chat_history import InMemoryChatMessageHistory
6
+ from langchain_core.messages import SystemMessage
7
+ from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate, MessagesPlaceholder
8
+ from langchain_core.runnables.history import RunnableWithMessageHistory
9
+
10
+ from config import paths
11
+
12
+ CHINESE_SYSTEM_PROMPT = (
13
+ "你是善于模拟真实的思考过程的AI助手。"
14
+ "回答时,必须首先生成一个不超过5个字的简短句子,"
15
+ "比如:\"让我想一下\"、\"在我看来\"、\"稍等我理一理\"、\"不错的问题\"、\"稍等片刻\"等,然后再进行正式回答,"
16
+ "保持中文口语化表达,禁用emoji和系统相关描述,确保衔接词与内容存在合理逻辑关联。"
17
+ "/no_think"
18
+ )
19
+
20
+ ENGLISH_SYSTEM_PROMPT = (
21
+ "You are an AI assistant skilled at simulating authentic thinking processes. "
22
+ "When responding, you must first generate a brief phrase of no more than 5 words, "
23
+ "such as: 'Let me think', 'I see', 'Let me process this', 'Good question', 'One moment', etc., then proceed with your formal response. "
24
+ "Maintain natural conversational English expression, avoid emojis and system-related descriptions, and ensure logical coherence between transitional phrases and content."
25
+ "/no_think"
26
+ )
27
+
28
+
29
+ class TestLLMDialogue(unittest.TestCase):
30
+
31
+ def setUp(self):
32
+ model_params = {
33
+ 'n_ctx': 32768,
34
+ 'temperature': 0.7,
35
+ 'top_p': 0.9,
36
+ 'top_k': 20,
37
+ 'model_kwargs': {
38
+ 'mini_p': 0,
39
+ 'presence_penalty': 1.5
40
+ },
41
+ 'verbose': False
42
+ }
43
+ self.history_store = {}
44
+
45
+ model_path = paths.LLM_MODELS_PATH / 'qwen' / 'Qwen3-8B-Q6_K.gguf'
46
+ langchain_instance = ChatLlamaCpp(model_path=model_path.as_posix(), **model_params)
47
+
48
+ system_message = SystemMessage(content=CHINESE_SYSTEM_PROMPT)
49
+ human_message = HumanMessagePromptTemplate.from_template("{input}")
50
+ prompt = ChatPromptTemplate(messages=[
51
+ system_message,
52
+ MessagesPlaceholder(variable_name="history"),
53
+ human_message
54
+ ])
55
+
56
+ chain = prompt | langchain_instance
57
+ self.chain_with_history = RunnableWithMessageHistory(chain, self.get_session_history,
58
+ history_messages_key='history')
59
+ self.warmup()
60
+
61
+ # 连续对话测试问题集
62
+ self.user_questions = [
63
+ # 第1轮:开放性话题引入
64
+ "最近人工智能技术发展很快,你觉得AI对我们日常生活带来了哪些改变?",
65
+
66
+ # 第2轮:基于前一个回答的深入探讨
67
+ "你刚才提到的这些改变中,哪一个你认为是最重要的?为什么?",
68
+
69
+ # 第3轮:转向具体场景和个人观点
70
+ "如果让你选择一个AI应用来帮助解决教育领域的问题,你会选择什么?具体怎么实现?",
71
+
72
+ # 第4轮:挑战性问题,测试逻辑思维
73
+ "但是也有人担心AI在教育中会让学生过度依赖技术,失去独立思考能力。你怎么看待这个担忧?",
74
+
75
+ # 第5轮:总结性问题,测试整合能力
76
+ "综合我们刚才讨论的内容,你认为在AI快速发展的时代,普通人应该如何适应和准备?"
77
+ ]
78
+
79
+ def get_session_history(self, session_id: str) -> InMemoryChatMessageHistory:
80
+ if session_id not in self.history_store:
81
+ message_history = InMemoryChatMessageHistory()
82
+ self.history_store[session_id] = message_history
83
+ return self.history_store[session_id]
84
+
85
+ memory = ConversationBufferWindowMemory(
86
+ chat_memory=self.history_store[session_id],
87
+ k=3,
88
+ return_messages=True,
89
+ )
90
+ assert len(memory.memory_variables) == 1
91
+ key = memory.memory_variables[0]
92
+ messages = memory.load_memory_variables({})[key]
93
+ self.history_store[session_id] = InMemoryChatMessageHistory(messages=messages)
94
+ return self.history_store[session_id]
95
+
96
+ def warmup(self):
97
+ session_id = 'warmup'
98
+ config = {"configurable": {"session_id": session_id}}
99
+ for chunk in self.chain_with_history.stream(input={'input': 'This is a warmup step.'}, config=config):
100
+ pass
101
+
102
+ def test_dialogue(self):
103
+ session_id = 'test_dialogue'
104
+ for user_question in self.user_questions:
105
+ print('User question:', user_question)
106
+ config = {"configurable": {"session_id": session_id}}
107
+ print(f'LLM answer: ', end='')
108
+ for chunk in self.chain_with_history.stream(input={'input': user_question}, config=config):
109
+ print(chunk.content, end='')
110
+ print()
111
+ print('-' * 80)
112
+ print()