wrd 0.1.41__py3-none-any.whl → 1.0.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.
dune/llm_analyzer.py DELETED
@@ -1,197 +0,0 @@
1
- """
2
- Analizator LLM do interpretacji żądań w języku naturalnym.
3
- """
4
-
5
- import json
6
- import requests
7
- from typing import Dict, Any
8
- from loguru import logger
9
- from processor_engine import ProcessorConfig
10
-
11
-
12
- class LLMAnalyzer:
13
- """Analizator wykorzystujący LLM do interpretacji żądań."""
14
-
15
- def __init__(self, base_url: str = "http://localhost:11434", model: str = "mistral:7b"):
16
- self.base_url = base_url
17
- self.model = model
18
- self._check_ollama_connection()
19
-
20
- def _check_ollama_connection(self):
21
- """Sprawdza połączenie z Ollama."""
22
- try:
23
- response = requests.get(f"{self.base_url}/api/tags")
24
- if response.status_code == 200:
25
- logger.success("Połączenie z Ollama nawiązane")
26
- else:
27
- logger.warning("Ollama niedostępna, używanie domyślnych szablonów")
28
- except requests.RequestException:
29
- logger.warning("Nie można połączyć się z Ollama, używanie domyślnych szablonów")
30
-
31
- def analyze_request(self, request: str) -> ProcessorConfig:
32
- """Analizuje żądanie i zwraca konfigurację procesora."""
33
-
34
- # Spróbuj użyć LLM
35
- try:
36
- return self._analyze_with_llm(request)
37
- except Exception as e:
38
- logger.warning(f"LLM niedostępny ({e}), używanie domyślnego szablonu")
39
- return self._get_default_imap_processor()
40
-
41
- def _analyze_with_llm(self, request: str) -> ProcessorConfig:
42
- """Analizuje żądanie za pomocą LLM."""
43
-
44
- prompt = f"""
45
- Przeanalizuj poniższe żądanie i zwróć konfigurację procesora danych w formacie JSON.
46
-
47
- Żądanie: {request}
48
-
49
- Zwróć odpowiedź w następującym formacie JSON (tylko JSON, bez dodatkowych komentarzy):
50
- {{
51
- "name": "nazwa_procesora",
52
- "description": "opis działania",
53
- "dependencies": ["lista", "wymaganych", "pakietów"],
54
- "parameters": {{"parametr": "wartość"}},
55
- "code_template": "kompletny kod Python do wykonania zadania"
56
- }}
57
-
58
- Kod powinien:
59
- 1. Wykorzystywać zmienne środowiskowe z prefiksem IMAP_ dla połączenia
60
- 2. Zapisywać rezultat w zmiennej 'result'
61
- 3. Używać logger.info() do logowania
62
- 4. Tworzyć foldery zgodnie z żądaniem
63
- 5. Obsługiwać błędy
64
- """
65
-
66
- payload = {
67
- "model": self.model,
68
- "prompt": prompt,
69
- "stream": False,
70
- "options": {
71
- "temperature": 0.1,
72
- "top_p": 0.9
73
- }
74
- }
75
-
76
- response = requests.post(
77
- f"{self.base_url}/api/generate",
78
- json=payload,
79
- timeout=60
80
- )
81
- response.raise_for_status()
82
-
83
- result = response.json()
84
- response_text = result.get("response", "")
85
-
86
- # Wyodrębnij JSON z odpowiedzi
87
- json_start = response_text.find('{')
88
- json_end = response_text.rfind('}') + 1
89
-
90
- if json_start == -1 or json_end == 0:
91
- raise ValueError("Nie znaleziono JSON w odpowiedzi LLM")
92
-
93
- json_text = response_text[json_start:json_end]
94
- config_data = json.loads(json_text)
95
-
96
- return ProcessorConfig(**config_data)
97
-
98
- def _get_default_imap_processor(self) -> ProcessorConfig:
99
- """Zwraca domyślny procesor IMAP jako fallback."""
100
-
101
- code_template = '''
102
- import imaplib
103
- import email
104
- import os
105
- from datetime import datetime
106
- from pathlib import Path
107
-
108
- # Pobierz dane połączenia z zmiennych środowiskowych
109
- imap_server = os.getenv("IMAP_SERVER", "localhost")
110
- imap_port = int(os.getenv("IMAP_PORT", "143"))
111
- username = os.getenv("IMAP_USERNAME")
112
- password = os.getenv("IMAP_PASSWORD")
113
- use_ssl = os.getenv("IMAP_USE_SSL", "false").lower() == "true"
114
-
115
- if not username or not password:
116
- raise ValueError("Brak danych logowania IMAP w zmiennych środowiskowych")
117
-
118
- logger.info(f"Łączenie z serwerem IMAP: {imap_server}:{imap_port}")
119
-
120
- # Nawiąż połączenie
121
- if use_ssl:
122
- mail = imaplib.IMAP4_SSL(imap_server, imap_port)
123
- else:
124
- mail = imaplib.IMAP4(imap_server, imap_port)
125
-
126
- mail.login(username, password)
127
- mail.select("inbox")
128
-
129
- logger.info("Pobieranie listy wiadomości...")
130
-
131
- # Pobierz wszystkie wiadomości
132
- result, data = mail.search(None, "ALL")
133
- email_ids = data[0].split()
134
-
135
- downloaded_files = []
136
- base_path = Path(output_dir) / "skrzynka"
137
-
138
- logger.info(f"Znaleziono {len(email_ids)} wiadomości")
139
-
140
- for i, email_id in enumerate(email_ids):
141
- try:
142
- # Pobierz wiadomość
143
- result, msg_data = mail.fetch(email_id, "(RFC822)")
144
- email_body = msg_data[0][1]
145
- email_message = email.message_from_bytes(email_body)
146
-
147
- # Pobierz datę wiadomości
148
- date_header = email_message.get("Date")
149
- if date_header:
150
- try:
151
- date_tuple = email.utils.parsedate_tz(date_header)
152
- if date_tuple:
153
- timestamp = email.utils.mktime_tz(date_tuple)
154
- msg_date = datetime.fromtimestamp(timestamp)
155
- else:
156
- msg_date = datetime.now()
157
- except:
158
- msg_date = datetime.now()
159
- else:
160
- msg_date = datetime.now()
161
-
162
- # Utwórz folder rok.miesiąc
163
- year_month = f"{msg_date.year}.{msg_date.month:02d}"
164
- folder_path = base_path / year_month
165
- folder_path.mkdir(parents=True, exist_ok=True)
166
-
167
- # Zapisz plik .eml
168
- filename = folder_path / f"email_{email_id.decode()}.eml"
169
- with open(filename, "wb") as f:
170
- f.write(email_body)
171
-
172
- downloaded_files.append(str(filename))
173
- logger.info(f"Zapisano: {filename}")
174
-
175
- except Exception as e:
176
- logger.error(f"Błąd przetwarzania wiadomości {email_id}: {e}")
177
-
178
- mail.close()
179
- mail.logout()
180
-
181
- result = {
182
- "status": "completed",
183
- "downloaded_files": downloaded_files,
184
- "total_count": len(downloaded_files),
185
- "folders_created": list(set([str(Path(f).parent) for f in downloaded_files]))
186
- }
187
-
188
- logger.success(f"Pobrano {len(downloaded_files)} wiadomości do {len(result['folders_created'])} folderów")
189
- '''
190
-
191
- return ProcessorConfig(
192
- name="imap_email_downloader",
193
- description="Pobiera wiadomości email z IMAP i organizuje je w foldery rok.miesiąc",
194
- dependencies=["imaplib", "email"],
195
- parameters={},
196
- code_template=code_template
197
- )
dune/processor_engine.py DELETED
@@ -1,114 +0,0 @@
1
- """
2
- Główny silnik procesora danych z dynamicznym zarządzaniem bibliotekami.
3
- """
4
-
5
- import os
6
- import sys
7
- import subprocess
8
- import importlib
9
- import json
10
- from typing import Dict, List, Any, Optional
11
- from pathlib import Path
12
- from loguru import logger
13
- from pydantic import BaseModel
14
-
15
-
16
- class ProcessorConfig(BaseModel):
17
- """Konfiguracja procesora danych."""
18
- name: str
19
- description: str
20
- dependencies: List[str]
21
- parameters: Dict[str, Any]
22
- code_template: str
23
-
24
-
25
- class DynamicPackageManager:
26
- """Menedżer dynamicznego instalowania pakietów."""
27
-
28
- def __init__(self):
29
- self.installed_packages = set()
30
-
31
- def install_package(self, package_name: str) -> bool:
32
- """Instaluje pakiet jeśli nie jest zainstalowany."""
33
- if package_name in self.installed_packages:
34
- return True
35
-
36
- try:
37
- logger.info(f"Instalowanie pakietu: {package_name}")
38
- subprocess.check_call([
39
- sys.executable, "-m", "pip", "install", package_name
40
- ], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
41
-
42
- self.installed_packages.add(package_name)
43
- logger.success(f"Pakiet {package_name} zainstalowany pomyślnie")
44
- return True
45
-
46
- except subprocess.CalledProcessError as e:
47
- logger.error(f"Błąd instalacji pakietu {package_name}: {e}")
48
- return False
49
-
50
- def import_module(self, module_name: str):
51
- """Importuje moduł po ewentualnej instalacji."""
52
- try:
53
- return importlib.import_module(module_name)
54
- except ImportError:
55
- # Spróbuj zainstalować i zaimportować ponownie
56
- if self.install_package(module_name):
57
- return importlib.import_module(module_name)
58
- raise
59
-
60
-
61
- class ProcessorEngine:
62
- """Główny silnik procesora danych."""
63
-
64
- def __init__(self, llm_analyzer):
65
- self.llm_analyzer = llm_analyzer
66
- self.package_manager = DynamicPackageManager()
67
- self.output_dir = Path(os.getenv("OUTPUT_DIR", "./output"))
68
- self.output_dir.mkdir(exist_ok=True)
69
-
70
- def process_natural_request(self, request: str) -> Dict[str, Any]:
71
- """Przetwarza żądanie w języku naturalnym."""
72
-
73
- # 1. Przeanalizuj żądanie za pomocą LLM
74
- logger.info("Analizowanie żądania za pomocą LLM...")
75
- processor_config = self.llm_analyzer.analyze_request(request)
76
-
77
- # 2. Zainstaluj wymagane biblioteki
78
- logger.info("Instalowanie wymaganych bibliotek...")
79
- for dependency in processor_config.dependencies:
80
- self.package_manager.install_package(dependency)
81
-
82
- # 3. Wykonaj kod procesora
83
- logger.info("Wykonywanie procesora danych...")
84
- return self._execute_processor(processor_config)
85
-
86
- def _execute_processor(self, config: ProcessorConfig) -> Dict[str, Any]:
87
- """Wykonuje procesor danych na podstawie konfiguracji."""
88
-
89
- # Przygotuj kontekst wykonania
90
- execution_context = {
91
- 'os': __import__('os'),
92
- 'sys': __import__('sys'),
93
- 'Path': Path,
94
- 'logger': logger,
95
- 'output_dir': str(self.output_dir),
96
- 'package_manager': self.package_manager,
97
- }
98
-
99
- # Dodaj zmienne środowiskowe
100
- for key, value in os.environ.items():
101
- if key.startswith(('IMAP_', 'EMAIL_', 'SMTP_')):
102
- execution_context[key.lower()] = value
103
-
104
- # Wykonaj kod
105
- try:
106
- exec(config.code_template, execution_context)
107
-
108
- # Pobierz wynik z kontekstu
109
- result = execution_context.get('result', {'status': 'completed'})
110
- return result
111
-
112
- except Exception as e:
113
- logger.error(f"Błąd wykonania procesora: {e}")
114
- raise