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.
- atcdr/ai.py +434 -0
- atcdr/cli.py +2 -2
- atcdr/download.py +32 -27
- atcdr/login.py +10 -11
- atcdr/logout.py +4 -3
- atcdr/markdown.py +9 -5
- atcdr/open.py +5 -4
- atcdr/submit.py +21 -24
- atcdr/test.py +21 -16
- atcdr/util/fileops.py +5 -4
- atcdr/util/i18n.py +317 -0
- atcdr/util/openai.py +45 -0
- atcdr/util/parse.py +15 -10
- atcdr/util/problem.py +3 -2
- atcdr/util/session.py +15 -14
- atcoderstudybooster-0.4.2.dist-info/METADATA +249 -0
- atcoderstudybooster-0.4.2.dist-info/RECORD +22 -0
- atcdr/generate.py +0 -202
- atcdr/util/gpt.py +0 -118
- atcoderstudybooster-0.4.0.dist-info/METADATA +0 -261
- atcoderstudybooster-0.4.0.dist-info/RECORD +0 -21
- {atcoderstudybooster-0.4.0.dist-info → atcoderstudybooster-0.4.2.dist-info}/WHEEL +0 -0
- {atcoderstudybooster-0.4.0.dist-info → atcoderstudybooster-0.4.2.dist-info}/entry_points.txt +0 -0
@@ -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
|
+

|
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
|