thonny-pai 0.13.0__tar.gz
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.
- thonny_pai-0.13.0/PKG-INFO +3 -0
- thonny_pai-0.13.0/README.txt +8 -0
- thonny_pai-0.13.0/pai/__init__.py +3 -0
- thonny_pai-0.13.0/pai/api.txt +7 -0
- thonny_pai-0.13.0/pai/core.py +65 -0
- thonny_pai-0.13.0/pyproject.toml +13 -0
- thonny_pai-0.13.0/setup.cfg +4 -0
- thonny_pai-0.13.0/thonny_pai.egg-info/PKG-INFO +3 -0
- thonny_pai-0.13.0/thonny_pai.egg-info/SOURCES.txt +10 -0
- thonny_pai-0.13.0/thonny_pai.egg-info/dependency_links.txt +1 -0
- thonny_pai-0.13.0/thonny_pai.egg-info/top_level.txt +2 -0
- thonny_pai-0.13.0/thonnycontrib/pai_assistant/__init__.py +52 -0
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
1. Mở pai\api.txt, thay key mẫu bằng key thật (mỗi dòng 1 key).
|
|
2
|
+
2. Gỡ bản cũ, rồi cài:
|
|
3
|
+
"C:\Users\Monett-Windows\AppData\Local\Programs\Thonny\python.exe" -m pip uninstall -y pai thonny-ai-link
|
|
4
|
+
"C:\Users\Monett-Windows\AppData\Local\Programs\Thonny\python.exe" -m pip install --force-reinstall "C:\Users\Monett-Windows\Downloads\pai-project"
|
|
5
|
+
3. Khởi động lại Thonny.
|
|
6
|
+
4. Code:
|
|
7
|
+
import pai
|
|
8
|
+
pai.request("câu hỏi")
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import time
|
|
4
|
+
import tempfile
|
|
5
|
+
import urllib.request
|
|
6
|
+
|
|
7
|
+
BASE_URL = "https://revidapi.com"
|
|
8
|
+
MODEL = "claude-sonnet-5"
|
|
9
|
+
SYSTEM_PROMPT = (
|
|
10
|
+
"Khi viết code: không dùng bất kỳ chú thích nào (không #, //, /* */, docstring, "
|
|
11
|
+
"hay chú thích cuối dòng). Luôn chọn thuật toán tối ưu nhất về hiệu năng và độ ngắn gọn."
|
|
12
|
+
)
|
|
13
|
+
API_FILE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "api.txt")
|
|
14
|
+
ANSWER_FILE = os.path.join(tempfile.gettempdir(), "thonny_ai_answer.json")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _load_keys():
|
|
18
|
+
try:
|
|
19
|
+
with open(API_FILE, encoding="utf-8") as f:
|
|
20
|
+
return [line.strip() for line in f if line.strip()]
|
|
21
|
+
except Exception:
|
|
22
|
+
return []
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _call_api(key, question):
|
|
26
|
+
body = json.dumps({
|
|
27
|
+
"model": MODEL,
|
|
28
|
+
"max_tokens": 1000,
|
|
29
|
+
"messages": [
|
|
30
|
+
{"role": "system", "content": SYSTEM_PROMPT},
|
|
31
|
+
{"role": "user", "content": question},
|
|
32
|
+
],
|
|
33
|
+
}).encode("utf-8")
|
|
34
|
+
|
|
35
|
+
req = urllib.request.Request(
|
|
36
|
+
BASE_URL + "/v1/chat/completions",
|
|
37
|
+
data=body,
|
|
38
|
+
method="POST",
|
|
39
|
+
headers={
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
"Authorization": "Bearer " + key,
|
|
42
|
+
},
|
|
43
|
+
)
|
|
44
|
+
with urllib.request.urlopen(req, timeout=120) as r:
|
|
45
|
+
data = json.loads(r.read().decode("utf-8"))
|
|
46
|
+
|
|
47
|
+
text = data["choices"][0]["message"]["content"]
|
|
48
|
+
if not text:
|
|
49
|
+
raise ValueError("empty response")
|
|
50
|
+
return text
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def request(question):
|
|
54
|
+
"""Hỏi AI. Lỗi key nào thì tự chuyển sang key tiếp theo, không in ra lỗi."""
|
|
55
|
+
for key in _load_keys():
|
|
56
|
+
try:
|
|
57
|
+
text = _call_api(key, question)
|
|
58
|
+
except Exception:
|
|
59
|
+
continue
|
|
60
|
+
|
|
61
|
+
with open(ANSWER_FILE, "w", encoding="utf-8") as f:
|
|
62
|
+
json.dump({"id": time.time_ns(), "text": text}, f, ensure_ascii=False)
|
|
63
|
+
return text
|
|
64
|
+
|
|
65
|
+
return None
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "thonny-pai"
|
|
7
|
+
version = "0.13.0"
|
|
8
|
+
|
|
9
|
+
[tool.setuptools]
|
|
10
|
+
packages = ["pai", "thonnycontrib.pai_assistant"]
|
|
11
|
+
|
|
12
|
+
[tool.setuptools.package-data]
|
|
13
|
+
pai = ["api.txt"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
import tempfile
|
|
4
|
+
|
|
5
|
+
from thonny import get_workbench
|
|
6
|
+
|
|
7
|
+
ANSWER_FILE = os.path.join(tempfile.gettempdir(), "thonny_ai_answer.json")
|
|
8
|
+
_last_id = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _read_answer():
|
|
12
|
+
try:
|
|
13
|
+
with open(ANSWER_FILE, encoding="utf-8") as f:
|
|
14
|
+
return json.load(f)
|
|
15
|
+
except Exception:
|
|
16
|
+
return None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _copy_to_clipboard(text):
|
|
20
|
+
wb = get_workbench()
|
|
21
|
+
wb.clipboard_clear()
|
|
22
|
+
wb.clipboard_append(text)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def _show(text, answer_id):
|
|
26
|
+
shell = get_workbench().get_view("ShellView").text
|
|
27
|
+
tag = f"pai_copy_{answer_id}"
|
|
28
|
+
|
|
29
|
+
shell.insert("end", "\n. ")
|
|
30
|
+
|
|
31
|
+
shell.tag_configure(tag, foreground="#f1f1f1", underline=True)
|
|
32
|
+
shell.tag_bind(tag, "<Button-1>", lambda e: _copy_to_clipboard(text))
|
|
33
|
+
shell.tag_bind(tag, "<Enter>", lambda e: shell.config(cursor="hand2"))
|
|
34
|
+
shell.tag_bind(tag, "<Leave>", lambda e: shell.config(cursor=""))
|
|
35
|
+
shell.insert("end", "Check your code", (tag,))
|
|
36
|
+
shell.see("end")
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _poll():
|
|
40
|
+
global _last_id
|
|
41
|
+
data = _read_answer()
|
|
42
|
+
if data and data.get("id") != _last_id:
|
|
43
|
+
_last_id = data.get("id")
|
|
44
|
+
_show(data["text"], _last_id)
|
|
45
|
+
get_workbench().after(500, _poll)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def load_plugin():
|
|
49
|
+
global _last_id
|
|
50
|
+
old = _read_answer()
|
|
51
|
+
_last_id = old.get("id") if old else None
|
|
52
|
+
get_workbench().after(500, _poll)
|