comp-ai-task 0.1.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.
- comp_ai_task-0.1.0/PKG-INFO +48 -0
- comp_ai_task-0.1.0/README.md +35 -0
- comp_ai_task-0.1.0/comp_ai/__init__.py +147 -0
- comp_ai_task-0.1.0/pyproject.toml +32 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: comp-ai-task
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Fast AI calls using task['query'] syntax in Python
|
|
5
|
+
Project-URL: Homepage, https://github.com/yourusername/comp-ai
|
|
6
|
+
Author: Marat
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
|
|
14
|
+
# comp_ai
|
|
15
|
+
|
|
16
|
+
Удобная библиотека для мгновенных запросов к ИИ прямо в Python IDLE или скриптах.
|
|
17
|
+
|
|
18
|
+
## Установка (после публикации на PyPI)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install comp-ai-task
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Использование в Python IDLE
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from comp_ai import *
|
|
28
|
+
|
|
29
|
+
# Отправка запроса:
|
|
30
|
+
task["Напиши стих про космос"]
|
|
31
|
+
|
|
32
|
+
# Или как функция:
|
|
33
|
+
task("Объясни теорию относительности за 2 предложения")
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Настройка API-ключа
|
|
37
|
+
|
|
38
|
+
При первом обращении библиотека сама попросит ввести API-ключ Gemini и сохранит его локально.
|
|
39
|
+
|
|
40
|
+
Также ключ можно указать:
|
|
41
|
+
1. В коде:
|
|
42
|
+
```python
|
|
43
|
+
task.set_key("AIzaSy...")
|
|
44
|
+
```
|
|
45
|
+
2. Через переменную окружения:
|
|
46
|
+
```bash
|
|
47
|
+
set GEMINI_API_KEY=AIzaSy...
|
|
48
|
+
```
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# comp_ai
|
|
2
|
+
|
|
3
|
+
Удобная библиотека для мгновенных запросов к ИИ прямо в Python IDLE или скриптах.
|
|
4
|
+
|
|
5
|
+
## Установка (после публикации на PyPI)
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install comp-ai-task
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Использование в Python IDLE
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from comp_ai import *
|
|
15
|
+
|
|
16
|
+
# Отправка запроса:
|
|
17
|
+
task["Напиши стих про космос"]
|
|
18
|
+
|
|
19
|
+
# Или как функция:
|
|
20
|
+
task("Объясни теорию относительности за 2 предложения")
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Настройка API-ключа
|
|
24
|
+
|
|
25
|
+
При первом обращении библиотека сама попросит ввести API-ключ Gemini и сохранит его локально.
|
|
26
|
+
|
|
27
|
+
Также ключ можно указать:
|
|
28
|
+
1. В коде:
|
|
29
|
+
```python
|
|
30
|
+
task.set_key("AIzaSy...")
|
|
31
|
+
```
|
|
32
|
+
2. Через переменную окружения:
|
|
33
|
+
```bash
|
|
34
|
+
set GEMINI_API_KEY=AIzaSy...
|
|
35
|
+
```
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
comp_ai - модуль для быстрых запросов к ИИ в Python IDLE и скриптах.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import json
|
|
9
|
+
import urllib.request
|
|
10
|
+
import urllib.error
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Optional
|
|
13
|
+
|
|
14
|
+
CONFIG_FILE = Path.home() / ".comp_ai_key"
|
|
15
|
+
|
|
16
|
+
class AITask:
|
|
17
|
+
def __init__(self, model: str = "gemini-3.6-flash"):
|
|
18
|
+
self.model = model
|
|
19
|
+
self._api_key: Optional[str] = None
|
|
20
|
+
self._load_key()
|
|
21
|
+
|
|
22
|
+
def _load_key(self):
|
|
23
|
+
"""Загрузка ключа из переменных окружения или файла"""
|
|
24
|
+
env_key = os.getenv("GEMINI_API_KEY")
|
|
25
|
+
if env_key:
|
|
26
|
+
self._api_key = env_key.strip()
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
if CONFIG_FILE.exists():
|
|
30
|
+
try:
|
|
31
|
+
cached_key = CONFIG_FILE.read_text(encoding="utf-8").strip()
|
|
32
|
+
if cached_key:
|
|
33
|
+
self._api_key = cached_key
|
|
34
|
+
except Exception:
|
|
35
|
+
pass
|
|
36
|
+
|
|
37
|
+
def set_key(self, api_key: str, save_locally: bool = True):
|
|
38
|
+
"""Установка ключа API"""
|
|
39
|
+
self._api_key = api_key.strip()
|
|
40
|
+
if save_locally:
|
|
41
|
+
try:
|
|
42
|
+
CONFIG_FILE.write_text(self._api_key, encoding="utf-8")
|
|
43
|
+
except Exception:
|
|
44
|
+
pass
|
|
45
|
+
print("[comp_ai] API-ключ сохранен!")
|
|
46
|
+
|
|
47
|
+
@property
|
|
48
|
+
def key(self) -> Optional[str]:
|
|
49
|
+
return self._api_key
|
|
50
|
+
|
|
51
|
+
@key.setter
|
|
52
|
+
def key(self, value: str):
|
|
53
|
+
self.set_key(value)
|
|
54
|
+
|
|
55
|
+
def _ensure_api_key(self) -> str:
|
|
56
|
+
"""Запрос ключа, если он не найден"""
|
|
57
|
+
if self._api_key:
|
|
58
|
+
return self._api_key
|
|
59
|
+
|
|
60
|
+
print("\n" + "=" * 50)
|
|
61
|
+
print(" [comp_ai] API-ключ Gemini не найден!")
|
|
62
|
+
print(" Получить бесплатный ключ: https://aistudio.google.com/app/apikey")
|
|
63
|
+
print("=" * 50)
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
user_input = input(" Введите ваш GEMINI_API_KEY: ").strip()
|
|
67
|
+
except (EOFError, KeyboardInterrupt):
|
|
68
|
+
user_input = ""
|
|
69
|
+
|
|
70
|
+
if not user_input:
|
|
71
|
+
raise ValueError(
|
|
72
|
+
"API-ключ не указан! Задайте его через task.set_key('...') или переменную GEMINI_API_KEY"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
self.set_key(user_input, save_locally=True)
|
|
76
|
+
return self._api_key
|
|
77
|
+
|
|
78
|
+
def query(self, prompt: str) -> str:
|
|
79
|
+
"""Вызов Gemini API"""
|
|
80
|
+
api_key = self._ensure_api_key()
|
|
81
|
+
|
|
82
|
+
# Если модель не сработала, пробуем fallback-модели
|
|
83
|
+
fallback_models = [self.model, "gemini-2.0-flash", "gemini-1.5-flash"]
|
|
84
|
+
# Убираем дубликаты сохраняя порядок
|
|
85
|
+
models_to_try = []
|
|
86
|
+
for m in fallback_models:
|
|
87
|
+
if m not in models_to_try:
|
|
88
|
+
models_to_try.append(m)
|
|
89
|
+
|
|
90
|
+
last_error = ""
|
|
91
|
+
for mod in models_to_try:
|
|
92
|
+
url = f"https://generativelanguage.googleapis.com/v1beta/models/{mod}:generateContent?key={api_key}"
|
|
93
|
+
headers = {"Content-Type": "application/json"}
|
|
94
|
+
payload = {"contents": [{"parts": [{"text": str(prompt)}]}]}
|
|
95
|
+
|
|
96
|
+
req = urllib.request.Request(
|
|
97
|
+
url,
|
|
98
|
+
data=json.dumps(payload).encode("utf-8"),
|
|
99
|
+
headers=headers,
|
|
100
|
+
method="POST"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
try:
|
|
104
|
+
with urllib.request.urlopen(req) as resp:
|
|
105
|
+
resp_data = json.loads(resp.read().decode("utf-8"))
|
|
106
|
+
candidates = resp_data.get("candidates", [])
|
|
107
|
+
if not candidates:
|
|
108
|
+
text_res = "[Пустой ответ от модели]"
|
|
109
|
+
else:
|
|
110
|
+
parts = candidates[0].get("content", {}).get("parts", [])
|
|
111
|
+
text_res = "".join(p.get("text", "") for p in parts)
|
|
112
|
+
|
|
113
|
+
# Запоминаем рабочую модель
|
|
114
|
+
self.model = mod
|
|
115
|
+
print(text_res)
|
|
116
|
+
return text_res
|
|
117
|
+
|
|
118
|
+
except urllib.error.HTTPError as e:
|
|
119
|
+
error_body = e.read().decode("utf-8", errors="ignore")
|
|
120
|
+
last_error = f"[Ошибка API Gemini {e.code}]: {error_body}"
|
|
121
|
+
if e.code == 404:
|
|
122
|
+
# Пробуем следующую модель из списка
|
|
123
|
+
continue
|
|
124
|
+
else:
|
|
125
|
+
print(last_error, file=sys.stderr)
|
|
126
|
+
return last_error
|
|
127
|
+
except Exception as e:
|
|
128
|
+
last_error = f"[Ошибка запроса]: {e}"
|
|
129
|
+
print(last_error, file=sys.stderr)
|
|
130
|
+
return last_error
|
|
131
|
+
|
|
132
|
+
print(last_error, file=sys.stderr)
|
|
133
|
+
return last_error
|
|
134
|
+
|
|
135
|
+
def __getitem__(self, prompt: str) -> str:
|
|
136
|
+
return self.query(prompt)
|
|
137
|
+
|
|
138
|
+
def __call__(self, prompt: str) -> str:
|
|
139
|
+
return self.query(prompt)
|
|
140
|
+
|
|
141
|
+
def __repr__(self) -> str:
|
|
142
|
+
status = "готов" if self._api_key else "ожидает ключ"
|
|
143
|
+
return f"<comp_ai.task (модель: {self.model}, статус: {status})>"
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
task = AITask()
|
|
147
|
+
__all__ = ["task", "AITask"]
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "comp-ai-task"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Fast AI calls using task['query'] syntax in Python"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Marat" }
|
|
14
|
+
]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[tool.hatch.build.targets.wheel]
|
|
22
|
+
packages = ["comp_ai"]
|
|
23
|
+
|
|
24
|
+
[tool.hatch.build.targets.sdist]
|
|
25
|
+
include = [
|
|
26
|
+
"/comp_ai",
|
|
27
|
+
"/README.md",
|
|
28
|
+
"/pyproject.toml"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
"Homepage" = "https://github.com/yourusername/comp-ai"
|