File size: 6,926 Bytes
ffa29f9
 
 
 
 
 
 
ecb1303
5979615
ecb1303
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5979615
ecb1303
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38f9863
ecb1303
4a49db9
ecb1303
 
5979615
 
 
ecb1303
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5979615
ecb1303
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5979615
ecb1303
 
 
 
f8a2bfb
ecb1303
 
 
 
f8a2bfb
ecb1303
 
 
 
 
 
 
 
 
 
 
 
f8a2bfb
a4c829d
 
 
 
5979615
4a49db9
5979615
4a49db9
a4c829d
 
ecb1303
 
5979615
 
ecb1303
 
 
 
 
 
 
 
 
 
 
 
 
83cf371
ecb1303
83cf371
ecb1303
 
 
 
 
 
 
 
 
 
5979615
 
 
ecb1303
 
 
 
 
 
38f9863
ecb1303
 
 
 
 
 
 
 
 
 
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
"""
このスクリプトは、自然言語処理モデルを使用してユーザーからの入力に対する応答を生成するためのユーティリティ関数を提供します。
特に、Chain of Thought (CoT) 技術を活用し、モデルが論理的かつ詳細な思考過程を踏まえた応答を生成できるよう設計されています。

作成者: aolans
日付: 2024/12/17
"""


def generate_cot_one( model, tokenizer, input: str ) -> str:
	"""
	inputに対して、CoTプロンプトを作成の後推論することで回答精度を上げている
	
	引数:
	model : モデル
	tokenizer : トークナイザ
	input (str): ユーザーからの入力文字列。

	戻り値:
	output_str (str): 応答内容(思考の過程を含む)
	"""

	# CoT用systemプロンプト
	prompt = f"""
### 指示:
あなたは優秀で論理的なアシスタントです。
ユーザーから指定が無い限り、日本語で記載してください。
1. まずは<Thought></Thought>タグの中であなたの思考の過程を抜けがないように記載していきます。ユーザーからの指示に対して、ステップごとに詳細を詰めていきます。ここでは最終的にユーザーに提供するべき情報がすべて記載されるべきです。思考を進めていく中で、定期的に過去の思考過程を見直し、内容や方向性の修正を行います。
2. <Output></Output>タグの中に最終的にユーザーに提供する出力を記載します。ユーザーは<Output></Output>の中だけ見ることになるので、回答として必要となる情報はすべて記載されるべきです。 タグは必ず閉じなければなりません。

### 入力:
{input}

### 思考:
<Thought>"""

	# *** 推論 ***
	input_ids = tokenizer(prompt, return_tensors="pt").to(model.device)
	outputs = model.generate(**input_ids, max_new_tokens=1024, do_sample=False, repetition_penalty=1.2,)
	prediction = tokenizer.decode(outputs[0][input_ids.input_ids.size(1):], skip_special_tokens=True)

	# *** 不要文字除去 ***
	# <Thought></Thought>除去
	output_str = remove_tags( prediction, "Thought" )
	# <Output></Output>除去
	output_str = remove_tags( output_str, "Output" )
	# 「### 応答:」を変換
	output_str = output_str.replace( "### 応答:", "【回答】\n" )
	return output_str




def generate_cot_two( model, tokenizer, input: str ) -> str:
	"""
	inputに対するCoTプロンプトを適用し回答精度を上げる
	「思考過程」と「回答」の2回に分けて推論する。
	思考の過程と応用内容を別々に取得可能
	
	引数:
	model : モデル
	tokenizer : トークナイザ
	input (str): ユーザーからの入力文字列。

	戻り値:
	thought (str): 思考の過程
	answer (str): 応答内容
	"""

	#  *****************  思考過程作成  **********************
	prompt_1 = f"""
### 指示:
あなたは優秀で論理的なアシスタントです。
<Thought></Thought>タグの中であなたの思考の過程を抜けがないように記載していきます。
ユーザーからの指示に対して、ステップごとに詳細を詰めていきます。
ここでは最終的にユーザーに提供するべき情報がすべて記載されるべきです。
思考を進めていく中で、定期的に過去の思考過程を見直し、内容や方向性の修正を行います。
入力に対する直接の回答は避けて、思考の過程のみを記載してください。
日本語で記載しなさい。

### 入力:
{input}

### 思考:
<Thought>"""

	# *** 推論(思考過程) ***
	input_ids_1 = tokenizer(prompt_1, return_tensors="pt").to(model.device)
	outputs_1 = model.generate(**input_ids_1, max_new_tokens=1024, do_sample=False, repetition_penalty=1.2,)
	thought = tokenizer.decode(outputs_1[0][input_ids_1.input_ids.size(1):], skip_special_tokens=True)


	#  *****************  応答作成  **********************
	prompt_2 = f"""
### 指示:
あなたは優秀で論理的なアシスタントです。
<Thought></Thought>タグの内容を参考にして、<Output></Output>タグの中に最終的にユーザーに提供する出力を記載します。
ユーザーは<Output></Output>の中だけ見ることになるので、回答として必要となる情報はすべて記載されるべきです。
タグは必ず閉じなければなりません。
ユーザーから指定が無い限り、基本的に日本語で記載しなさい。

### 入力:
{input}

<out>
### 思考:
{thought}

### 応答:
<Output>"""

	# *** 推論(応答) ***
	input_ids_2 = tokenizer(prompt_2, return_tensors="pt").to(model.device)
	outputs_2 = model.generate(**input_ids_2, max_new_tokens=1024, do_sample=False, repetition_penalty=1.2,)
	answers = tokenizer.decode(outputs_2[0][input_ids_2.input_ids.size(1):], skip_special_tokens=True)

	# *** 不要文字除去 ***
	# <Thought></Thought>除去
	thought = remove_tags( thought, "Thought" )
	# <Output></Output>除去
	answers = remove_tags( answers, "Output" )

	output = tokenizer.decode(outputs_2[0], skip_special_tokens=True).split('<out>')[-1]
	# <Thought></Thought>除去
	output = remove_tags( output, "Thought" )
	# <Output></Output>除去
	output = remove_tags( output, "Output" )
	# 「### 思考:」を変換
	output = output.replace( "### 思考:", "【思考の過程】" )
	# 「### 応答:」を変換
	output = output.replace( "### 応答:", "【回答】\n" )

	return output, answers, thought




def generate_simple( model, tokenizer, input: str ) -> str:
	"""
	単純なプロンプトで推論。 通常はこちらを選択
	
	引数:
	model : モデル
	tokenizer : トークナイザ
	input (str): ユーザーからの入力文字列。

	戻り値:
	output (str): 応答内容
	"""

	prompt = f"""### 指示
{input}
### 回答
"""

	# *** 推論 ***
	input_ids = tokenizer(prompt, return_tensors="pt").to(model.device)
	outputs = model.generate(**input_ids, max_new_tokens=1024, do_sample=False, repetition_penalty=1.2,)
	prediction = tokenizer.decode(outputs[0][input_ids.input_ids.size(1):], skip_special_tokens=True)

	return prediction





def remove_tags( str_in_tag: str, tag_name: str ) -> str:
	"""
	出力文字列から<Thought>および<Output>タグを削除する関数です。
	
	引数:
	str_in_tag (str): タグを削除したい文字列。
	tag_name (str): タグの名前(例: <Output><\Output> ⇒ Output )
	
	戻り値:
	str_removed (str): タグが削除された文字列。
	"""

	str_removed = str_in_tag.replace(f"\n<{tag_name}>\n", "\n").replace(f"\n<{tag_name}>", "\n").replace(f"<{tag_name}>\n", "\n").replace(f"<{tag_name}>", "")
	str_removed = str_removed.replace(f"\n</{tag_name}>\n", "\n").replace(f"\n</{tag_name}>", "\n").replace(f"</{tag_name}>\n", "\n").replace(f"</{tag_name}>", "\n")

	return str_removed