AtCoderStudyBooster 0.4.0__py3-none-any.whl → 0.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.3
2
+ Name: AtCoderStudyBooster
3
+ Version: 0.4.2
4
+ Summary: A tool to download and manage AtCoder problems.
5
+ Project-URL: Homepage, https://github.com/yuta6/AtCoderStudyBooster
6
+ Author-email: yuta6 <46110512+yuta6@users.noreply.github.com>
7
+ License: MIT
8
+ Requires-Python: >=3.8
9
+ Requires-Dist: beautifulsoup4
10
+ Requires-Dist: click-aliases>=1.0.5
11
+ Requires-Dist: markdownify==0.13.1
12
+ Requires-Dist: openai>=1.99.6
13
+ Requires-Dist: pywebview>=5.4
14
+ Requires-Dist: questionary>=2.0.1
15
+ Requires-Dist: requests
16
+ Requires-Dist: rich-click>=1.8.8
17
+ Requires-Dist: rich>=13.7.1
18
+ Requires-Dist: tiktoken
19
+ Requires-Dist: types-beautifulsoup4>=4.12.0.20240511
20
+ Requires-Dist: types-requests>=2.32.0.20240712
21
+ Description-Content-Type: text/markdown
22
+
23
+ # AtCoderStudyBooster
24
+
25
+ [日本語版 README はこちら](README.ja.md)
26
+
27
+ ## Overview
28
+
29
+ 🚧 This project is still in experimental stage. We are continuously adding features to help with daily AtCoder practice.
30
+
31
+ ![demo image](./.images/demo0.gif)
32
+
33
+ AtCoderStudyBooster is a CLI tool designed to accelerate your AtCoder learning journey. It supports downloading problems locally, testing, submitting, and generating solutions. Python installation is required. If you have Python installed, you can install this tool with:
34
+
35
+ ```sh
36
+ pip install AtCoderStudyBooster
37
+ ```
38
+
39
+ (Python 3.8 or higher is required)
40
+
41
+ Even after CAPTCHA authentication was introduced, you can still login and submit semi-automatically from CLI. However, you need to manually solve the CAPTCHA through GUI. This tool does not bypass CAPTCHA authentication.
42
+
43
+ This project is strongly influenced by:
44
+ - [online-judge-tools](https://github.com/online-judge-tools)
45
+ - [atcoder-cli](https://github.com/Tatamo/atcoder-cli)
46
+
47
+ ## Use Cases
48
+
49
+ Let's start by using the `download` command to download problems locally.
50
+
51
+ ### 1. Download a Specific Contest
52
+
53
+ Examples for downloading problems from a single contest.
54
+
55
+ #### Download all problems from ABC350
56
+ ```sh
57
+ ❯ atcdr download abc350
58
+ ```
59
+
60
+ #### Download problems A-D from ABC350
61
+ ```sh
62
+ ❯ atcdr download abc350 {A..D}
63
+ ```
64
+
65
+ #### Download Typical 90 Problems
66
+ ```sh
67
+ ❯ atcdr download typical90
68
+ ```
69
+
70
+ ### 2. Batch Download Multiple Contests
71
+
72
+ Examples for downloading multiple contests at once. Utilizes bash brace expansion.
73
+
74
+ #### All problems from ABC001 to ABC010
75
+ ```sh
76
+ ❯ atcdr download abc{001..010}
77
+ ```
78
+
79
+ #### Specific problems from multiple contests
80
+ ```sh
81
+ ❯ atcdr download abc{301..310} {A..C}
82
+ ```
83
+
84
+ ### 3. Download Specific Difficulty Problems
85
+
86
+ Examples for collecting problems of the same difficulty across different contests.
87
+
88
+ #### Download all A problems from ABC301-310
89
+ ```sh
90
+ ❯ atcdr download A abc{301..310}
91
+ ```
92
+
93
+ This creates the following directory structure:
94
+ ```
95
+ A/
96
+ ├── abc301/
97
+ │ ├── Problem.html
98
+ │ └── Problem.md
99
+ ├── abc302/
100
+ │ ├── Problem.html
101
+ │ └── Problem.md
102
+ └── ...
103
+ ```
104
+
105
+ #### Download all B problems from ABC300-302
106
+ ```sh
107
+ ❯ atcdr download B abc{300..302}
108
+ ```
109
+
110
+ Creates:
111
+ ```
112
+ B/
113
+ ├── abc300/
114
+ │ ├── Problem.html
115
+ │ └── Problem.md
116
+ ├── abc301/
117
+ │ ├── Problem.html
118
+ │ └── Problem.md
119
+ └── abc302/
120
+ ├── Problem.html
121
+ └── Problem.md
122
+ ```
123
+ This directory structure allows you to efficiently practice problems of the same difficulty level in one place.
124
+
125
+ ### Solving Problems
126
+
127
+ You can view problems by opening Markdown or HTML files with VS Code's HTML Preview or Markdown Preview. In VS Code, you can display the text editor on the left and work on problems while viewing them on the right.
128
+
129
+ ### Testing Samples Locally
130
+
131
+ Navigate to the folder where you downloaded the problem.
132
+
133
+ ```sh
134
+ ❯ cd abc224/B
135
+ ```
136
+
137
+ After creating your solution file in the folder, run the test command to test against sample cases.
138
+
139
+ ```sh
140
+ ~/.../abc224/B
141
+ ❯ atcdr t
142
+ ```
143
+
144
+ For Wrong Answer (WA) cases, the display looks like this:
145
+
146
+ ### Submitting Solutions
147
+
148
+ ```sh
149
+ ~/.../abc224/B
150
+ ❯ atcdr s
151
+ ```
152
+
153
+ Running this command will submit your solution. Login to AtCoder website is required for submission.
154
+
155
+ ### Generating Solutions with GPT
156
+
157
+ ```sh
158
+ ~/.../abc224/B
159
+ ❯ atcdr g
160
+ ```
161
+
162
+ This command generates a solution using OpenAI's GPT model. An OpenAI API key is required. On first run, you'll be prompted to input your API key.
163
+
164
+ ### Login to AtCoder
165
+
166
+ ```sh
167
+ ❯ atcdr login
168
+ ```
169
+
170
+ Logs into AtCoder. A browser window will open for CAPTCHA verification. After solving the CAPTCHA, login completes automatically.
171
+
172
+ ### Create Markdown File
173
+
174
+ ```sh
175
+ ~/.../abc224/B
176
+ ❯ atcdr m
177
+ ```
178
+
179
+ Creates a Markdown file from the HTML file in the current directory. This command is automatically executed during `atcdr download`.
180
+
181
+ ### Open Problem in Browser
182
+
183
+ ```sh
184
+ ~/.../abc224/B
185
+ ❯ atcdr o
186
+ ```
187
+
188
+ Opens the problem page in your browser. Convenient for checking detailed problem statements or constraints.
189
+
190
+ ## Commands
191
+
192
+ | Command | Alias | Description |
193
+ |---------|-------|-------------|
194
+ | `atcdr download` | `atcdr d` | Download problems |
195
+ | `atcdr test` | `atcdr t` | Test with sample cases |
196
+ | `atcdr submit` | `atcdr s` | Submit solution |
197
+ | `atcdr generate` | `atcdr g` | Generate solution with GPT |
198
+ | `atcdr login` | - | Login to AtCoder |
199
+ | `atcdr logout` | - | Logout from AtCoder |
200
+ | `atcdr markdown` | `atcdr m` | Create Markdown file |
201
+ | `atcdr open` | `atcdr o` | Open problem in browser |
202
+
203
+ ## GPT Code Generation
204
+
205
+ `atcdr generate` command uses GPT to generate solutions. It requires an OpenAI API key.
206
+
207
+ ### Generate Solution with Test
208
+
209
+ By default, generated code is tested against sample cases:
210
+
211
+ ```sh
212
+ ~/.../abc224/B
213
+ ❯ atcdr generate
214
+ ```
215
+
216
+ ### Specify Language
217
+
218
+ Specify the programming language for generation. Default is Python.
219
+
220
+ ```sh
221
+ ~/.../abc224/B
222
+ ❯ atcdr generate --lang cpp
223
+ ```
224
+
225
+ Supported languages:
226
+ - `python` (default)
227
+ - `cpp`
228
+ - `java`
229
+ - `rust`
230
+
231
+ ### Specify GPT Model
232
+
233
+ ```sh
234
+ ~/.../abc224/B
235
+ ❯ atcdr generate --gpt gpt-4o
236
+ ```
237
+
238
+ Available models:
239
+ - `gpt-4o-mini` (default) - Fast and cost-effective
240
+ - `gpt-4o` - More accurate but slower
241
+
242
+ ### Generate Code Only Without Testing
243
+
244
+ To generate code without testing:
245
+
246
+ ```sh
247
+ ~/.../abc224/B
248
+ ❯ atcdr generate --lang rust --without_test
249
+ ```
@@ -0,0 +1,22 @@
1
+ atcdr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ atcdr/ai.py,sha256=mjGfst2PaxgKskGkBVyrsNsSDlkgsQeyhPK9I8hOq-w,15894
3
+ atcdr/cli.py,sha256=KPpnxqlvUwiXZdGmaO07bv3sRFJezjyXs0HPqF9r5I4,2562
4
+ atcdr/download.py,sha256=sMILF_FKLTe3OBk_ZnA8pzvnlGz68jrHaU-lxDAy6pA,7678
5
+ atcdr/login.py,sha256=3lyuo19EKOj3eaiOcOUnrkkgEEqWO0D1EnjLPKNxkPU,4655
6
+ atcdr/logout.py,sha256=XwyR5oSipg-iQzfdfkx4Cs0Q88ZWJ548FmdhlIhpUL8,777
7
+ atcdr/markdown.py,sha256=x0OORs1eun14c0XZWUap6HljTHhJ6UM6OfkJlDXeeSo,1587
8
+ atcdr/open.py,sha256=bxfoUGO0yo3BK1C9iswuN65GW_wp6OEa58IX7JgWAFU,1319
9
+ atcdr/submit.py,sha256=vVGZ-04K7NtjL5jv79Wx8IWosVK44XwEDCK19QAkKAo,9604
10
+ atcdr/test.py,sha256=tbjkBETQG48AuH1F_hBlla3lpfcQiVvFO1YjZ2QDB9A,13518
11
+ atcdr/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
+ atcdr/util/fileops.py,sha256=kvQDO85Ii5n__Wo8KmoE6Ecgbxx9MfmF7BDYz1sL5Sk,3200
13
+ atcdr/util/filetype.py,sha256=pceB08trkwNkdzKJx4fFfOWpz9jYMBRDwXLW4un0sRM,2254
14
+ atcdr/util/i18n.py,sha256=WRptkwqRSYSpA7L2CeWwv4ufv_uK65KjnorAcOTOot8,17949
15
+ atcdr/util/openai.py,sha256=BygabBuUmuD7wCyEujS4-79XpmLaBi8L_mGUq-JsTGs,1232
16
+ atcdr/util/parse.py,sha256=fPcDqnb-COGJA49sc8HLNQBjCATII0edOtpe_sVIx0g,7121
17
+ atcdr/util/problem.py,sha256=ZLD-WvhC5SC6TGbyqmiOpTVZVSn-KuhOazWvAvHdyqI,1222
18
+ atcdr/util/session.py,sha256=xct266SY7QuC3bc1IKlkVginttvXE_qK5tepUx6hfWE,4820
19
+ atcoderstudybooster-0.4.2.dist-info/METADATA,sha256=RKaWJkW3AiRZeIDRTQuhGshxruW7CvTo_lUbZmzi6gE,6107
20
+ atcoderstudybooster-0.4.2.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
21
+ atcoderstudybooster-0.4.2.dist-info/entry_points.txt,sha256=-stL-IwnheQGlYAdm82RuZu8CGgSakU0aVIVlA7DmFA,40
22
+ atcoderstudybooster-0.4.2.dist-info/RECORD,,
atcdr/generate.py DELETED
@@ -1,202 +0,0 @@
1
- import json
2
- import os
3
- import re
4
-
5
- import rich_click as click
6
- from rich.console import Console
7
- from rich.panel import Panel
8
- from rich.syntax import Syntax
9
-
10
- from atcdr.test import ResultStatus, TestRunner, create_renderable_test_info
11
- from atcdr.util.fileops import add_file_selector
12
- from atcdr.util.filetype import (
13
- FILE_EXTENSIONS,
14
- Filename,
15
- Lang,
16
- lang2str,
17
- str2lang,
18
- )
19
- from atcdr.util.gpt import ChatGPT, Model, set_api_key
20
- from atcdr.util.parse import ProblemHTML
21
-
22
-
23
- def get_code_from_gpt_output(output: str) -> str:
24
- pattern = re.compile(r'```(?:\w+)?\s*(.*?)\s*```', re.DOTALL)
25
- match = pattern.search(output)
26
- return match.group(1) if match else ''
27
-
28
-
29
- def render_result_for_GPT(
30
- test: TestRunner,
31
- ) -> tuple[str, bool]:
32
- results = list(test)
33
-
34
- match test.info.summary:
35
- case ResultStatus.AC:
36
- return 'Accepted', True
37
- case ResultStatus.CE:
38
- return f'Compile Error \n {test.info.compiler_message}', False
39
- case _:
40
- message_for_gpt = ''.join(
41
- f'\n{result.label} => {result.result.passed.value}\nInput :\n{result.testcase.input}\nOutput :\n{result.result.output}\nExpected :\n{result.testcase.output}\n'
42
- if result.result.passed == ResultStatus.WA
43
- else f'\n{result.label} => {result.result.passed.value}\nInput :\n{result.testcase.input}\nOutput :\n{result.result.output}\n'
44
- for result in results
45
- )
46
- return message_for_gpt, False
47
-
48
-
49
- def generate_code(file: Filename, lang: Lang, model: Model) -> None:
50
- console = Console()
51
- with open(file, 'r') as f:
52
- html_content = f.read()
53
- md = ProblemHTML(html_content).make_problem_markdown('en')
54
-
55
- if set_api_key() is None:
56
- return
57
- gpt = ChatGPT(
58
- system_prompt=f"""You are an excellent programmer. You solve problems in competitive programming.When a user provides you with a problem from a programming contest called AtCoder, including the Problem,Constraints, Input, Output, Input Example, and Output Example, please carefully consider these and solve the problem.Make sure that your output code block contains no more than two blocks. Pay close attention to the Input, Input Example, Output, and Output Example.Create the solution in {lang2str(lang)}.""",
59
- model=model,
60
- )
61
- with console.status(f'コード生成中 (by {gpt.model.value})'):
62
- reply = gpt.tell(md)
63
-
64
- code = get_code_from_gpt_output(reply)
65
- console.print('[green][+][/green] コードの生成に成功しました. ')
66
- console.rule(f'{gpt.model.value}による{lang2str(lang)}コード')
67
- console.print(Syntax(code=code, lexer=lang2str(lang)))
68
-
69
- saved_filename = (
70
- os.path.splitext(file)[0] + f'_by_{gpt.model.value}' + FILE_EXTENSIONS[lang]
71
- )
72
- with open(saved_filename, 'w') as f:
73
- console.print(
74
- f'[green][+][/green] {gpt.model.value} の出力したコードを保存しました:{f.name}'
75
- )
76
- f.write(code)
77
-
78
-
79
- def generate_template(file: Filename, lang: Lang) -> None:
80
- console = Console()
81
- with open(file, 'r') as f:
82
- html_content = f.read()
83
- md = ProblemHTML(html_content).make_problem_markdown('en')
84
-
85
- if set_api_key() is None:
86
- return
87
- gpt = ChatGPT(
88
- system_prompt='You are a highly skilled programmer. Your role is to create a template code for competitive programming.',
89
- temperature=0.0,
90
- )
91
-
92
- propmpt = f"""
93
- The user will provide a problem from a programming contest called AtCoder. This problem will include the Problem Statement, Constraints, Input, Output, Input Example, and Output Example. You should focus on the Constraints and Input sections to create the template in {lang2str(lang)}.
94
-
95
- - First, create the part of the code that handles input. Then, you should read ###Input Block and ###Constraints Block.
96
- - After receiving the input, define variables in the program by reading ###Constraints Block and explain how to use the variables in the comment of your code block with example.
97
- - Last, define variables needed for output. Then you should read ###Output Block and ###Constraints Block.
98
-
99
- You must not solve the problem. Please faithfully reproduce the variable names defined in the problem.
100
- """
101
- with console.status(f'{lang2str(lang)}のテンプレートを生成しています...'):
102
- reply = gpt.tell(md + propmpt)
103
- code = get_code_from_gpt_output(reply)
104
-
105
- savaed_filename = os.path.splitext(file)[0] + FILE_EXTENSIONS[lang]
106
- with open(savaed_filename, 'x') as f:
107
- console.print(
108
- f'[green][+][/green] テンプレートファイルを作成 :{savaed_filename}'
109
- )
110
- f.write(code)
111
-
112
-
113
- def solve_problem(file: Filename, lang: Lang, model: Model) -> None:
114
- console = Console()
115
- with open(file, 'r') as f:
116
- html = ProblemHTML(f.read())
117
-
118
- md = html.make_problem_markdown('en')
119
- labeled_cases = html.load_labeled_testcase()
120
-
121
- if set_api_key() is None:
122
- return
123
- gpt = ChatGPT(
124
- system_prompt=f"""You are a brilliant programmer. Your task is to solve an AtCoder problem. AtCoder is a platform that hosts programming competitions where participants write programs to solve algorithmic challenges.Please solve the problem in {lang2str(lang)}.""",
125
- model=model,
126
- )
127
-
128
- file_without_ext = os.path.splitext(file)[0]
129
-
130
- for i in range(1, 4):
131
- with console.status(f'{i}回目のコード生成中 (by {gpt.model.value})'):
132
- if i == 1:
133
- test_report = ''
134
- reply = gpt.tell(md)
135
- else:
136
- prompt = f"""The following is the test report for the code you provided:
137
- {test_report}
138
- Please provide an updated version of the code in {lang2str(lang)}."""
139
- console.print(
140
- f'[green][+][/] 次のプロンプトを{gpt.model.value}に与え,再生成します'
141
- )
142
- console.print(Panel(prompt))
143
- reply = gpt.tell(prompt)
144
-
145
- code = get_code_from_gpt_output(reply)
146
-
147
- saved_filename = (
148
- f'{i}_'
149
- + file_without_ext
150
- + f'_by_{gpt.model.value}'
151
- + FILE_EXTENSIONS[lang]
152
- )
153
- with open(saved_filename, 'w') as f:
154
- console.print(f'[green][+][/] コードの生成に成功しました!:{f.name}')
155
- f.write(code)
156
-
157
- with console.status(
158
- f'{gpt.model.value}が生成したコードをテスト中', spinner='circleHalves'
159
- ):
160
- test = TestRunner(saved_filename, labeled_cases)
161
- test_report, is_ac = render_result_for_GPT(test)
162
-
163
- console.print(create_renderable_test_info(test.info))
164
-
165
- if is_ac:
166
- console.print('[green][+][/] コードのテストに成功!')
167
- break
168
- else:
169
- console.print('[red][-][/] コードのテストに失敗!')
170
-
171
- with open(
172
- 'log_'
173
- + file_without_ext
174
- + f'_by_{gpt.model.value}'
175
- + FILE_EXTENSIONS[Lang.JSON],
176
- 'w',
177
- ) as f:
178
- console.print(
179
- f'[green][+][/] {gpt.model.value}の出力のログを保存しました:{f.name}'
180
- )
181
- f.write(json.dumps(gpt.messages, indent=2))
182
- return
183
-
184
-
185
- @click.command(short_help='コードを生成')
186
- @add_file_selector('files', filetypes=[Lang.HTML])
187
- @click.option('--lang', default='Python', help='出力するプログラミング言語')
188
- @click.option('--model', default=Model.GPT41_MINI.value, help='使用するGPTモデル')
189
- @click.option('--without-test', is_flag=True, help='テストケースを省略して生成')
190
- @click.option('--template', is_flag=True, help='テンプレートを生成')
191
- def generate(files, lang, model, without_test, template):
192
- """HTMLファイルからコード生成またはテンプレート出力を行います。"""
193
- la = str2lang(lang)
194
- model_enum = Model(model)
195
-
196
- for path in files:
197
- if template:
198
- generate_template(path, la)
199
- elif without_test:
200
- generate_code(path, la, model_enum)
201
- else:
202
- solve_problem(path, la, model_enum)
atcdr/util/gpt.py DELETED
@@ -1,118 +0,0 @@
1
- import os
2
- from enum import Enum
3
- from typing import Dict, List, Optional
4
-
5
- import requests
6
-
7
-
8
- class Model(Enum):
9
- GPT4O = 'gpt-4o'
10
- GPT41 = 'gpt-4.1'
11
- GPT41_MINI = 'gpt-4.1-mini'
12
- GPT41_NANO = 'gpt-4.1-nano'
13
- GPT4O_MINI = 'gpt-4o-mini'
14
- O1_PREVIEW = 'o1-preview'
15
- O1 = 'o1'
16
- O3 = 'o3'
17
- O1_MINI = 'o1-mini'
18
- O3_MINI = 'o3-mini'
19
- O4_MINI = 'o4-mini'
20
-
21
-
22
- def set_api_key() -> Optional[str]:
23
- api_key = os.getenv('OPENAI_API_KEY')
24
- if api_key and validate_api_key(api_key):
25
- return api_key
26
- elif api_key:
27
- print('環境変数に設定されているAPIキーの検証に失敗しました ')
28
- else:
29
- pass
30
-
31
- api_key = input(
32
- 'https://platform.openai.com/api-keys からchatGPTのAPIキーを入手しましょう。\nAPIキー入力してください: '
33
- )
34
- if validate_api_key(api_key):
35
- print('APIキーのテストに成功しました。')
36
- print('以下, ~/.zshrcにAPIキーを保存しますか? [y/n]')
37
- if input() == 'y':
38
- zshrc_path = os.path.expanduser('~/.zshrc')
39
- with open(zshrc_path, 'a') as f:
40
- f.write(f'export OPENAI_API_KEY={api_key}\n')
41
- print(
42
- f'APIキーを {zshrc_path} に保存しました。次回シェル起動時に読み込まれます。'
43
- )
44
- os.environ['OPENAI_API_KEY'] = api_key
45
- return api_key
46
- else:
47
- print('コード生成にはAPIキーが必要です。')
48
- return None
49
-
50
-
51
- def validate_api_key(api_key: str) -> bool:
52
- headers = {
53
- 'Content-Type': 'application/json',
54
- 'Authorization': f'Bearer {api_key}',
55
- }
56
-
57
- response = requests.get('https://api.openai.com/v1/models', headers=headers)
58
-
59
- if response.status_code == 200:
60
- return True
61
- else:
62
- print('APIキーの検証に失敗しました。')
63
- return False
64
-
65
-
66
- class ChatGPT:
67
- API_URL = 'https://api.openai.com/v1/chat/completions'
68
-
69
- # APIの使い方 https://platform.openai.com/docs/api-reference/making-requests
70
- def __init__(
71
- self,
72
- api_key: Optional[str] = None,
73
- model: Model = Model.GPT41_MINI,
74
- max_tokens: int = 3000,
75
- temperature: float = 0.7,
76
- messages: Optional[List[Dict[str, str]]] = None,
77
- system_prompt: str = 'You are a helpful assistant.',
78
- ) -> None:
79
- self.api_key = api_key or os.getenv('OPENAI_API_KEY')
80
- self.model = model
81
- self.max_tokens = max_tokens
82
- self.temperature = temperature
83
- self.messages = (
84
- messages
85
- if messages is not None
86
- else [{'role': 'system', 'content': system_prompt}]
87
- )
88
-
89
- self.__headers = {
90
- 'Content-Type': 'application/json',
91
- 'Authorization': f'Bearer {self.api_key}',
92
- }
93
-
94
- def tell(self, message: str) -> str:
95
- self.messages.append({'role': 'user', 'content': message})
96
-
97
- settings = {
98
- 'model': self.model.value,
99
- 'messages': self.messages,
100
- 'max_tokens': self.max_tokens,
101
- 'temperature': self.temperature,
102
- }
103
-
104
- response = requests.post(self.API_URL, headers=self.__headers, json=settings)
105
- responsej = response.json()
106
- try:
107
- reply = responsej['choices'][0]['message']['content']
108
- except KeyError:
109
- print('Error:レスポンスの形式が正しくありません. \n' + str(responsej))
110
- return 'Error: Unable to retrieve response.'
111
-
112
- self.messages.append({'role': 'assistant', 'content': reply})
113
-
114
- # usage = responsej['usage']
115
- # input_tokens = usage.get('prompt_tokens', 0)
116
- # output_tokens = usage.get('completion_tokens', 0)
117
-
118
- return reply