-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsolver.py
188 lines (157 loc) · 5.83 KB
/
solver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""
Codes related to CoTSolver
"""
from abc import ABC, abstractmethod
from typing import override
from agent import ChatBot
COT_AI_PROMPT = (
"Let's first understand the problem, extract relevant variables and their corresponding numerals,"
"and **devise a plan**. Then, let's **carry out the plan**, caculate intermediate results"
"(pay attention to calculation and common sense), solve the problem step by step, and show the answer."
)
class CoTSolver(ABC):
"""
Chain-of-Thought Solver
"""
@abstractmethod
def solve(self) -> str:
"""
Solve the problem.
Returns:
- the final answer
"""
@abstractmethod
def set_problem(self, problem: str):
"""
Set the problem description to be solved.
NOTICE: The options should not be contained if it's a multiple choices problem.
"""
@abstractmethod
def send_human_message(self, msg: str) -> ChatBot:
"""
get the agent
"""
def solve_numerical(self) -> str:
"""
Solve a numerical problem, e.g. return only a number.
"""
self.solve()
return self.send_human_message(
"Therefore the answer is?"
"Output only a real number(e.g., 3.14). Do not use fractional form(like 1/2 or 3/4)."
"Do not show a equation like 1 + 1 = 2. In this case, output 2 only."
"If your answer is a repeating decimal, round it to six decimal places."
)
def solve_multichoice(self, options: dict[str, str]) -> str:
"""
Solve a multiple-choice question, e.g. return one of [A, B, C, D, E, ...]
"""
self.solve()
options_lines = []
for k, v in options.items():
options_lines.append(f"{k}: {v}")
return self.send_human_message(
f"Here are {len(options_lines)} options for the answer:\n"
+ "\n".join(options_lines)
+ "Please choose and output one of the upper letter of the options, e.g. A. "
"If you think none of them is correct, just output the most likely letter."
"Do not output anything beside the letter like A"
"Please do not use bold formatting in your output."
)
def solve_boolean(self, boolean_expression: tuple[str, str]):
"""
Args:
boolean_expression: two str in a tuple, presenting true and false. e.g. ["True", "False"]
"""
self.solve()
return self.send_human_message(
"Decide the answer to the problem to be true or false."
f"If you think it's true, output {boolean_expression[0]},"
f"else output {boolean_expression[1]}"
f"Do not output anything beside the judgment like f{boolean_expression[0]}."
)
class ZSCoTSolver(CoTSolver):
"""
Wraps an agent and use zero-shot CoT to solve a problem(usually math).
"""
def __init__(self, problem: str = None, model_name: str = None):
self._problem = problem
self._agent = ChatBot(model_name=model_name)
@override
def send_human_message(self, msg):
return self._agent.post_human(msg)
def set_problem(self, problem: str) -> None:
"""
Simple Setter
"""
self._problem = problem
@override
def solve(self) -> str:
"""
Solve the problem.
Returns:
- a number indicates the final answer
"""
self._agent.clear_history()
self._agent.store_human(self._problem)
return self._agent.post_ai("Let's think step by step.")
class PSCoTSolver(CoTSolver):
"""
Wraps an agent and use Plan-and-Solve CoT to solve a problem(usually math).
"""
def __init__(self, problem: str = None, model_name: str = None):
self._problem = problem
self._agent = ChatBot(model_name=model_name)
@override
def send_human_message(self, msg):
return self._agent.post_human(msg)
def set_problem(self, problem: str):
"""
Simple Setter
"""
self._problem = problem
def solve(self) -> str:
"""
Solve the problem.
Returns:
- a number indicates the final answer
"""
self._agent.clear_history()
self._agent.store_human(self._problem)
return self._agent.post_ai(COT_AI_PROMPT)
class GiveAListSolver(CoTSolver):
"""
Prompot the agent to give a list of steps to solve the problem
"""
def __init__(self, problem: str = None, model_name: str = None):
self._problem = problem
self._agent = ChatBot(
system_prompt=(
"You are going to solve a problem. "
"First, you should extract variables and their corresponding numerals."
"Second, make a list. Each element of the list is a track of how these variables evolve."
"The variable and its corresponding numerals should be included in the list."
"After each manipulation in the problem, the variable may change(or not)."
"You should clearly describe how the variable changes in the list."
"Finally, the last element of the list should be the final answer of the problem."
),
model_name=model_name,
)
@override
def send_human_message(self, msg):
return self._agent.post_human(msg)
def set_problem(self, problem: str):
"""
Simple Setter
"""
self._problem = problem
def solve(self) -> str:
"""
Prompt the agent to give a list of steps to solve the problem
"""
self._agent.clear_history()
self._agent.store_human(self._problem)
return self._agent.post_ai(
"Ok, I will think step by step and give you a list of steps to solve the problem.\n"
"1. "
)