ngpt 1.7.2__py3-none-any.whl → 2.1.0__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.
ngpt/cli.py CHANGED
@@ -85,7 +85,7 @@ def check_config(config):
85
85
 
86
86
  return True
87
87
 
88
- def interactive_chat_session(client, web_search=False, no_stream=False):
88
+ def interactive_chat_session(client, web_search=False, no_stream=False, temperature=0.7, top_p=1.0, max_length=None):
89
89
  """Run an interactive chat session with conversation history."""
90
90
  # Define ANSI color codes for terminal output
91
91
  COLORS = {
@@ -239,7 +239,10 @@ def interactive_chat_session(client, web_search=False, no_stream=False):
239
239
  prompt=user_input,
240
240
  messages=conversation,
241
241
  stream=not no_stream,
242
- web_search=web_search
242
+ web_search=web_search,
243
+ temperature=temperature,
244
+ top_p=top_p,
245
+ max_length=max_length
243
246
  )
244
247
 
245
248
  # Add AI response to conversation history
@@ -286,6 +289,12 @@ def main():
286
289
  help='Enable web search capability (Note: Your API endpoint must support this feature)')
287
290
  global_group.add_argument('-n', '--no-stream', action='store_true',
288
291
  help='Return the whole response without streaming')
292
+ global_group.add_argument('--temperature', type=float, default=0.7,
293
+ help='Set temperature (controls randomness, default: 0.7)')
294
+ global_group.add_argument('--top_p', type=float, default=1.0,
295
+ help='Set top_p (controls diversity, default: 1.0)')
296
+ global_group.add_argument('--max_length', type=int,
297
+ help='Set max response length in tokens')
289
298
 
290
299
  # Mode flags (mutually exclusive)
291
300
  mode_group = parser.add_argument_group('Modes (mutually exclusive)')
@@ -385,38 +394,20 @@ def main():
385
394
  print(f"Total configurations: {len(configs)}")
386
395
  print(f"Active configuration index: {args.config_index}")
387
396
 
388
- # Temporarily initialize a client to get the detected provider for each config
389
- def get_detected_provider(config):
390
- base_url = config.get('base_url', '')
391
- temp_client = NGPTClient(
392
- api_key=config.get('api_key', ''),
393
- base_url=base_url,
394
- provider=config.get('provider', 'N/A'),
395
- model=config.get('model', 'N/A')
396
- )
397
- detected = temp_client._detect_provider_from_url(base_url)
398
- return detected if detected else config.get('provider', 'N/A')
399
-
400
397
  if args.all:
401
398
  # Show details for all configurations
402
399
  print("\nAll configuration details:")
403
400
  for i, cfg in enumerate(configs):
404
401
  active_str = '(Active)' if i == args.config_index else ''
405
- detected_provider = get_detected_provider(cfg)
406
- provider_str = f" [{detected_provider}]" if detected_provider else ""
407
-
408
402
  print(f"\n--- Configuration Index {i} {active_str} ---")
409
- print(f" API Key: {'[Set]' if cfg.get('api_key') else '[Not Set]'}{provider_str}")
403
+ print(f" API Key: {'[Set]' if cfg.get('api_key') else '[Not Set]'}")
410
404
  print(f" Base URL: {cfg.get('base_url', 'N/A')}")
411
405
  print(f" Provider: {cfg.get('provider', 'N/A')}")
412
406
  print(f" Model: {cfg.get('model', 'N/A')}")
413
407
  else:
414
408
  # Show active config details and summary list
415
- detected_provider = get_detected_provider(active_config)
416
- provider_str = f" [{detected_provider}]" if detected_provider else ""
417
-
418
409
  print("\nActive configuration details:")
419
- print(f" API Key: {'[Set]' if active_config.get('api_key') else '[Not Set]'}{provider_str}")
410
+ print(f" API Key: {'[Set]' if active_config.get('api_key') else '[Not Set]'}")
420
411
  print(f" Base URL: {active_config.get('base_url', 'N/A')}")
421
412
  print(f" Provider: {active_config.get('provider', 'N/A')}")
422
413
  print(f" Model: {active_config.get('model', 'N/A')}")
@@ -425,9 +416,7 @@ def main():
425
416
  print("\nAvailable configurations:")
426
417
  for i, cfg in enumerate(configs):
427
418
  active_marker = "*" if i == args.config_index else " "
428
- detected = get_detected_provider(cfg)
429
- detected_str = f" [{detected}]" if detected else ""
430
- print(f"[{i}]{active_marker} {cfg.get('provider', 'N/A')} - {cfg.get('model', 'N/A')} ({'[API Key Set]' if cfg.get('api_key') else '[API Key Not Set]'}{detected_str})")
419
+ print(f"[{i}]{active_marker} {cfg.get('provider', 'N/A')} - {cfg.get('model', 'N/A')} ({'[API Key Set]' if cfg.get('api_key') else '[API Key Not Set]'})")
431
420
 
432
421
  return
433
422
 
@@ -464,7 +453,9 @@ def main():
464
453
  # Handle modes
465
454
  if args.interactive:
466
455
  # Interactive chat mode
467
- interactive_chat_session(client, web_search=args.web_search, no_stream=args.no_stream)
456
+ interactive_chat_session(client, web_search=args.web_search, no_stream=args.no_stream,
457
+ temperature=args.temperature, top_p=args.top_p,
458
+ max_length=args.max_length)
468
459
  elif args.shell:
469
460
  if args.prompt is None:
470
461
  try:
@@ -476,7 +467,9 @@ def main():
476
467
  else:
477
468
  prompt = args.prompt
478
469
 
479
- command = client.generate_shell_command(prompt, web_search=args.web_search)
470
+ command = client.generate_shell_command(prompt, web_search=args.web_search,
471
+ temperature=args.temperature, top_p=args.top_p,
472
+ max_length=args.max_length)
480
473
  if not command:
481
474
  return # Error already printed by client
482
475
 
@@ -512,7 +505,9 @@ def main():
512
505
  else:
513
506
  prompt = args.prompt
514
507
 
515
- generated_code = client.generate_code(prompt, args.language, web_search=args.web_search)
508
+ generated_code = client.generate_code(prompt, args.language, web_search=args.web_search,
509
+ temperature=args.temperature, top_p=args.top_p,
510
+ max_length=args.max_length)
516
511
  if generated_code:
517
512
  print(f"\nGenerated code:\n{generated_code}")
518
513
 
@@ -625,7 +620,9 @@ def main():
625
620
  sys.exit(130)
626
621
 
627
622
  print("\nSubmission successful. Waiting for response...")
628
- response = client.chat(prompt, stream=not args.no_stream, web_search=args.web_search)
623
+ response = client.chat(prompt, stream=not args.no_stream, web_search=args.web_search,
624
+ temperature=args.temperature, top_p=args.top_p,
625
+ max_tokens=args.max_length)
629
626
  if args.no_stream and response:
630
627
  print(response)
631
628
 
@@ -640,7 +637,9 @@ def main():
640
637
  sys.exit(130)
641
638
  else:
642
639
  prompt = args.prompt
643
- response = client.chat(prompt, stream=not args.no_stream, web_search=args.web_search)
640
+ response = client.chat(prompt, stream=not args.no_stream, web_search=args.web_search,
641
+ temperature=args.temperature, top_p=args.top_p,
642
+ max_tokens=args.max_length)
644
643
  if args.no_stream and response:
645
644
  print(response)
646
645
 
ngpt/client.py CHANGED
@@ -18,71 +18,19 @@ class NGPTClient:
18
18
  self.base_url = base_url if base_url.endswith('/') else base_url + '/'
19
19
  self.model = model
20
20
 
21
- # Detect provider based on base_url domain first
22
- detected_provider = self._detect_provider_from_url(self.base_url)
23
- self.provider = detected_provider if detected_provider else provider
24
-
25
21
  # Default headers
26
22
  self.headers = {
27
23
  "Content-Type": "application/json",
28
24
  "Authorization": f"Bearer {self.api_key}"
29
25
  }
30
26
 
31
- def _detect_provider_from_url(self, url: str) -> str:
32
- """
33
- Detect the API provider based on the base URL domain.
34
-
35
- Args:
36
- url: The base URL to analyze
37
-
38
- Returns:
39
- Detected provider name or empty string if not detected
40
- """
41
- import re
42
- from urllib.parse import urlparse
43
-
44
- # Extract domain from URL
45
- try:
46
- parsed_url = urlparse(url)
47
- domain = parsed_url.netloc.lower()
48
-
49
- # Check for known API provider domains
50
- if 'openai.com' in domain:
51
- return 'OpenAI'
52
- elif 'anthropic.com' in domain:
53
- return 'Anthropic'
54
- elif 'generativelanguage.googleapis.com' in domain:
55
- return 'Gemini'
56
- elif 'groq.com' in domain:
57
- return 'Groq'
58
- elif 'cohere.com' in domain or 'cohere.ai' in domain:
59
- return 'Cohere'
60
- elif 'mistral.ai' in domain:
61
- return 'Mistral'
62
- elif 'claude.ai' in domain:
63
- return 'Claude'
64
- elif re.match(r'(127\.0\.0\.1|localhost)', domain):
65
- # Local APIs, check path components for clues
66
- path = parsed_url.path.lower()
67
- if '/ollama' in path:
68
- return 'Ollama'
69
- elif '/llama' in path:
70
- return 'Llama'
71
- # Default to the explicitly provided provider for local APIs
72
- return ''
73
-
74
- # Return empty string if no match found, will fall back to provided provider
75
- return ''
76
- except Exception:
77
- # In case of any parsing error, fall back to provided provider
78
- return ''
79
-
80
27
  def chat(
81
28
  self,
82
29
  prompt: str,
83
30
  stream: bool = True,
84
31
  temperature: float = 0.7,
85
32
  max_tokens: Optional[int] = None,
33
+ top_p: float = 1.0,
86
34
  messages: Optional[List[Dict[str, str]]] = None,
87
35
  web_search: bool = False,
88
36
  **kwargs
@@ -95,6 +43,7 @@ class NGPTClient:
95
43
  stream: Whether to stream the response
96
44
  temperature: Controls randomness in the response
97
45
  max_tokens: Maximum number of tokens to generate
46
+ top_p: Controls diversity via nucleus sampling
98
47
  messages: Optional list of message objects to override default behavior
99
48
  web_search: Whether to enable web search capability
100
49
  **kwargs: Additional arguments to pass to the API
@@ -115,6 +64,7 @@ class NGPTClient:
115
64
  "messages": messages,
116
65
  "stream": stream,
117
66
  "temperature": temperature,
67
+ "top_p": top_p,
118
68
  }
119
69
 
120
70
  # Conditionally add web_search
@@ -132,26 +82,11 @@ class NGPTClient:
132
82
  endpoint = "chat/completions"
133
83
  url = f"{self.base_url}{endpoint}"
134
84
 
135
- # Set headers based on provider
136
- headers = self.headers.copy()
137
- provider = self.provider.lower() if hasattr(self, 'provider') else ""
138
-
139
- # Provider-specific customizations
140
- if 'gemini' in provider:
141
- # Gemini uses X-Goog-Api-Key instead of Bearer token
142
- headers = {
143
- "Content-Type": "application/json",
144
- "X-Goog-Api-Key": self.api_key
145
- }
146
-
147
- # Gemini may require a different endpoint or payload structure
148
- # This is a simplistic approach - may need further customization
149
-
150
85
  try:
151
86
  if not stream:
152
87
  # Regular request
153
88
  try:
154
- response = requests.post(url, headers=headers, json=payload)
89
+ response = requests.post(url, headers=self.headers, json=payload)
155
90
  response.raise_for_status() # Raise exception for HTTP errors
156
91
  result = response.json()
157
92
 
@@ -165,7 +100,7 @@ class NGPTClient:
165
100
  else:
166
101
  # Streaming request
167
102
  collected_content = ""
168
- with requests.post(url, headers=headers, json=payload, stream=True) as response:
103
+ with requests.post(url, headers=self.headers, json=payload, stream=True) as response:
169
104
  response.raise_for_status() # Raise exception for HTTP errors
170
105
 
171
106
  try:
@@ -226,13 +161,23 @@ class NGPTClient:
226
161
  print(f"Error: An unexpected error occurred: {e}")
227
162
  return ""
228
163
 
229
- def generate_shell_command(self, prompt: str, web_search: bool = False) -> str:
164
+ def generate_shell_command(
165
+ self,
166
+ prompt: str,
167
+ web_search: bool = False,
168
+ temperature: float = 0.4,
169
+ top_p: float = 0.95,
170
+ max_length: Optional[int] = None
171
+ ) -> str:
230
172
  """
231
173
  Generate a shell command based on the prompt.
232
174
 
233
175
  Args:
234
176
  prompt: Description of the command to generate
235
177
  web_search: Whether to enable web search capability
178
+ temperature: Controls randomness in the response
179
+ top_p: Controls diversity via nucleus sampling
180
+ max_length: Maximum number of tokens to generate
236
181
 
237
182
  Returns:
238
183
  The generated shell command
@@ -280,13 +225,24 @@ Command:"""
280
225
  prompt=prompt,
281
226
  stream=False,
282
227
  messages=messages,
283
- web_search=web_search
228
+ web_search=web_search,
229
+ temperature=temperature,
230
+ top_p=top_p,
231
+ max_tokens=max_length
284
232
  )
285
233
  except Exception as e:
286
234
  print(f"Error generating shell command: {e}")
287
235
  return ""
288
236
 
289
- def generate_code(self, prompt: str, language: str = "python", web_search: bool = False) -> str:
237
+ def generate_code(
238
+ self,
239
+ prompt: str,
240
+ language: str = "python",
241
+ web_search: bool = False,
242
+ temperature: float = 0.4,
243
+ top_p: float = 0.95,
244
+ max_length: Optional[int] = None
245
+ ) -> str:
290
246
  """
291
247
  Generate code based on the prompt.
292
248
 
@@ -294,6 +250,9 @@ Command:"""
294
250
  prompt: Description of the code to generate
295
251
  language: Programming language to generate code in
296
252
  web_search: Whether to enable web search capability
253
+ temperature: Controls randomness in the response
254
+ top_p: Controls diversity via nucleus sampling
255
+ max_length: Maximum number of tokens to generate
297
256
 
298
257
  Returns:
299
258
  The generated code
@@ -323,7 +282,10 @@ Code:"""
323
282
  prompt=prompt,
324
283
  stream=False,
325
284
  messages=messages,
326
- web_search=web_search
285
+ web_search=web_search,
286
+ temperature=temperature,
287
+ top_p=top_p,
288
+ max_tokens=max_length
327
289
  )
328
290
  except Exception as e:
329
291
  print(f"Error generating code: {e}")
@@ -339,77 +301,36 @@ Code:"""
339
301
  if not self.api_key:
340
302
  print("Error: API key is not set. Please configure your API key in the config file or provide it with --api-key.")
341
303
  return []
342
-
343
- provider = getattr(self, 'provider', '').lower()
344
-
345
- # Handle provider-specific API differences
346
- if 'gemini' in provider:
347
- # Gemini API specific handling
348
- # Base URL typically ends with /v1beta or similar - we want to add /models
349
- base_url = self.base_url.rstrip('/')
350
- if base_url.endswith('/v1beta'):
351
- url = f"{base_url}/models"
352
- else:
353
- url = f"{base_url}/models"
354
304
 
355
- # Gemini uses X-Goog-Api-Key instead of Bearer token
356
- headers = {
357
- "Content-Type": "application/json",
358
- "X-Goog-Api-Key": self.api_key
359
- }
305
+ # Endpoint for models
306
+ url = f"{self.base_url}models"
307
+
308
+ try:
309
+ response = requests.get(url, headers=self.headers)
310
+ response.raise_for_status() # Raise exception for HTTP errors
311
+ result = response.json()
360
312
 
361
- try:
362
- response = requests.get(url, headers=headers)
363
- response.raise_for_status()
364
- result = response.json()
365
-
366
- # Gemini API returns models in a different format
367
- if "models" in result:
368
- # Transform to match our expected format
369
- return [{"id": model.get("name", "").split("/")[-1],
370
- "owned_by": "Google"}
371
- for model in result["models"]]
372
- else:
373
- print("Error: Unexpected response format when retrieving Gemini models.")
374
- return []
375
-
376
- except requests.exceptions.HTTPError as e:
377
- print(f"HTTP Error with Gemini API: {e}")
313
+ if "data" in result:
314
+ return result["data"]
315
+ else:
316
+ print("Error: Unexpected response format when retrieving models.")
378
317
  return []
379
318
 
380
- except Exception as e:
381
- print(f"Error retrieving Gemini models: {e}")
382
- return []
383
- else:
384
- # Standard OpenAI-compatible endpoint
385
- url = f"{self.base_url}models"
319
+ except requests.exceptions.HTTPError as e:
320
+ if e.response.status_code == 401:
321
+ print("Error: Authentication failed. Please check your API key.")
322
+ elif e.response.status_code == 404:
323
+ print(f"Error: Models endpoint not found at {url}")
324
+ elif e.response.status_code == 429:
325
+ print("Error: Rate limit exceeded. Please try again later.")
326
+ else:
327
+ print(f"HTTP Error: {e}")
328
+ return []
386
329
 
387
- try:
388
- response = requests.get(url, headers=self.headers)
389
- response.raise_for_status() # Raise exception for HTTP errors
390
- result = response.json()
391
-
392
- if "data" in result:
393
- return result["data"]
394
- else:
395
- print("Error: Unexpected response format when retrieving models.")
396
- return []
397
-
398
- except requests.exceptions.HTTPError as e:
399
- if e.response.status_code == 401:
400
- print("Error: Authentication failed. Please check your API key.")
401
- elif e.response.status_code == 404:
402
- print(f"Error: Models endpoint not found at {url}")
403
- elif e.response.status_code == 429:
404
- print("Error: Rate limit exceeded. Please try again later.")
405
- else:
406
- print(f"HTTP Error: {e}")
407
- return []
408
-
409
- except requests.exceptions.ConnectionError:
410
- print(f"Error: Could not connect to {self.base_url}. Please check your internet connection and base URL.")
411
- return []
412
-
413
- except Exception as e:
414
- print(f"Error: An unexpected error occurred while retrieving models: {e}")
415
- return []
330
+ except requests.exceptions.ConnectionError:
331
+ print(f"Error: Could not connect to {self.base_url}. Please check your internet connection and base URL.")
332
+ return []
333
+
334
+ except Exception as e:
335
+ print(f"Error: An unexpected error occurred while retrieving models: {e}")
336
+ return []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ngpt
3
- Version: 1.7.2
3
+ Version: 2.1.0
4
4
  Summary: A lightweight Python CLI and library for interacting with OpenAI-compatible APIs, supporting both official and self-hosted LLM endpoints.
5
5
  Project-URL: Homepage, https://github.com/nazdridoy/ngpt
6
6
  Project-URL: Repository, https://github.com/nazdridoy/ngpt
@@ -37,14 +37,17 @@ Description-Content-Type: text/markdown
37
37
  [![PyPI version](https://img.shields.io/pypi/v/ngpt.svg)](https://pypi.org/project/ngpt/)
38
38
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
39
  [![Python Versions](https://img.shields.io/pypi/pyversions/ngpt.svg)](https://pypi.org/project/ngpt/)
40
+ [![Documentation](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://nazdridoy.github.io/ngpt/)
40
41
 
41
42
  A lightweight Python CLI and library for interacting with OpenAI-compatible APIs, supporting both official and self-hosted LLM endpoints.
42
43
 
43
44
  ## Table of Contents
44
45
  - [Quick Start](#quick-start)
45
46
  - [Features](#features)
47
+ - [Documentation](#documentation)
46
48
  - [Installation](#installation)
47
49
  - [Usage](#usage)
50
+ - [Documentation](https://nazdridoy.github.io/ngpt/)
48
51
  - [CLI Tool](#as-a-cli-tool)
49
52
  - [Python Library](#as-a-library)
50
53
  - [Configuration](#configuration)
@@ -93,6 +96,12 @@ ngpt --text
93
96
  - 🧩 **Clean Code Generation**: Output code without markdown or explanations
94
97
  - 📝 **Rich Multiline Editor**: Interactive multiline text input with syntax highlighting and intuitive controls
95
98
 
99
+ ## Documentation
100
+
101
+ Comprehensive documentation, including API reference, usage guides, and examples, is available at:
102
+
103
+ **[https://nazdridoy.github.io/ngpt/](https://nazdridoy.github.io/ngpt/)**
104
+
96
105
  ## Installation
97
106
 
98
107
  ```bash
@@ -121,9 +130,12 @@ ngpt --show-config
121
130
  # Show all configurations
122
131
  ngpt --show-config --all
123
132
 
124
- # List available models for the current configuration
133
+ # List available models for the active configuration
125
134
  ngpt --list-models
126
135
 
136
+ # List models for a specific configuration
137
+ ngpt --list-models --config-index 1
138
+
127
139
  # With custom options
128
140
  ngpt --api-key your-key --base-url http://your-endpoint --model your-model "Hello"
129
141
 
@@ -214,9 +226,12 @@ You can configure the client using the following options:
214
226
  | `--api-key` | API key for the service |
215
227
  | `--base-url` | Base URL for the API |
216
228
  | `--model` | Model to use |
217
- | `--list-models` | List all available models for the current configuration |
229
+ | `--list-models` | List all available models for the selected configuration (can be combined with --config-index) |
218
230
  | `--web-search` | Enable web search capability |
219
231
  | `-n, --no-stream` | Return the whole response without streaming |
232
+ | `--temperature` | Set temperature (controls randomness, default: 0.7) |
233
+ | `--top_p` | Set top_p (controls diversity, default: 1.0) |
234
+ | `--max_length` | Set maximum response length in tokens |
220
235
  | `--config` | Path to a custom configuration file or, when used without a value, enters interactive configuration mode |
221
236
  | `--config-index` | Index of the configuration to use (default: 0) |
222
237
  | `--remove` | Remove the configuration at the specified index (requires --config and --config-index) |
@@ -0,0 +1,9 @@
1
+ ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
2
+ ngpt/cli.py,sha256=wNjY-qUuvzODdzffbYqyydJiLfhIsEXXUs9qalqcpvs,30082
3
+ ngpt/client.py,sha256=75xmzO7e9wQ7y_LzZCacg3mkZdheewcBxB6moPftqYw,13067
4
+ ngpt/config.py,sha256=BF0G3QeiPma8l7EQyc37bR7LWZog7FHJQNe7uj9cr4w,6896
5
+ ngpt-2.1.0.dist-info/METADATA,sha256=47qdylepQUHyR-TsJTtB8ezMnRLnZie0uSI1WVbHUNg,11278
6
+ ngpt-2.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ ngpt-2.1.0.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
8
+ ngpt-2.1.0.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
9
+ ngpt-2.1.0.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- ngpt/__init__.py,sha256=ehInP9w0MZlS1vZ1g6Cm4YE1ftmgF72CnEddQ3Le9n4,368
2
- ngpt/cli.py,sha256=Ba3B4VAs-fnuSdfo22dAe2vmSy3ADVZlKYiDGTy6C6I,29818
3
- ngpt/client.py,sha256=qwAmBHSJvadbsvK5YPbY0By1M4bBvxd7j8piP5UdTgE,16553
4
- ngpt/config.py,sha256=BF0G3QeiPma8l7EQyc37bR7LWZog7FHJQNe7uj9cr4w,6896
5
- ngpt-1.7.2.dist-info/METADATA,sha256=uW2p_2ENm1OJLNW35nZcyDr_L0JvD5eeMrTvWGCPQmg,10568
6
- ngpt-1.7.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- ngpt-1.7.2.dist-info/entry_points.txt,sha256=1cnAMujyy34DlOahrJg19lePSnb08bLbkUs_kVerqdk,39
8
- ngpt-1.7.2.dist-info/licenses/LICENSE,sha256=mQkpWoADxbHqE0HRefYLJdm7OpdrXBr3vNv5bZ8w72M,1065
9
- ngpt-1.7.2.dist-info/RECORD,,
File without changes