seekrai 0.0.1__py3-none-any.whl → 0.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.
Files changed (45) hide show
  1. seekrai/__init__.py +0 -15
  2. seekrai/abstract/api_requestor.py +121 -297
  3. seekrai/client.py +10 -11
  4. seekrai/constants.py +36 -16
  5. seekrai/error.py +1 -8
  6. seekrai/filemanager.py +40 -79
  7. seekrai/resources/chat/completions.py +13 -13
  8. seekrai/resources/completions.py +4 -4
  9. seekrai/resources/embeddings.py +4 -2
  10. seekrai/resources/files.py +17 -9
  11. seekrai/resources/finetune.py +57 -82
  12. seekrai/resources/images.py +2 -2
  13. seekrai/resources/models.py +115 -15
  14. seekrai/types/__init__.py +5 -4
  15. seekrai/types/common.py +1 -2
  16. seekrai/types/files.py +23 -19
  17. seekrai/types/finetune.py +20 -26
  18. seekrai/types/models.py +26 -20
  19. seekrai/utils/_log.py +3 -3
  20. seekrai/utils/api_helpers.py +2 -2
  21. seekrai/utils/tools.py +1 -1
  22. seekrai-0.1.0.dist-info/METADATA +169 -0
  23. seekrai-0.1.0.dist-info/RECORD +39 -0
  24. seekrai/cli/__init__.py +0 -0
  25. seekrai/cli/api/__init__.py +0 -0
  26. seekrai/cli/api/chat.py +0 -245
  27. seekrai/cli/api/completions.py +0 -107
  28. seekrai/cli/api/files.py +0 -125
  29. seekrai/cli/api/finetune.py +0 -175
  30. seekrai/cli/api/images.py +0 -82
  31. seekrai/cli/api/models.py +0 -42
  32. seekrai/cli/cli.py +0 -77
  33. seekrai/legacy/__init__.py +0 -0
  34. seekrai/legacy/base.py +0 -27
  35. seekrai/legacy/complete.py +0 -91
  36. seekrai/legacy/embeddings.py +0 -25
  37. seekrai/legacy/files.py +0 -140
  38. seekrai/legacy/finetune.py +0 -173
  39. seekrai/legacy/images.py +0 -25
  40. seekrai/legacy/models.py +0 -44
  41. seekrai-0.0.1.dist-info/METADATA +0 -401
  42. seekrai-0.0.1.dist-info/RECORD +0 -56
  43. {seekrai-0.0.1.dist-info → seekrai-0.1.0.dist-info}/LICENSE +0 -0
  44. {seekrai-0.0.1.dist-info → seekrai-0.1.0.dist-info}/WHEEL +0 -0
  45. {seekrai-0.0.1.dist-info → seekrai-0.1.0.dist-info}/entry_points.txt +0 -0
seekrai/cli/api/files.py DELETED
@@ -1,125 +0,0 @@
1
- import json
2
- import pathlib
3
- from textwrap import wrap
4
-
5
- import click
6
- from tabulate import tabulate
7
-
8
- from seekrai import seekrflow
9
- from seekrai.types import FilePurpose
10
- from seekrai.utils import check_file, convert_bytes, convert_unix_timestamp
11
-
12
-
13
- @click.group()
14
- @click.pass_context
15
- def files(ctx: click.Context) -> None:
16
- """File API commands"""
17
- pass
18
-
19
-
20
- @files.command()
21
- @click.pass_context
22
- @click.argument(
23
- "file",
24
- type=click.Path(
25
- exists=True, file_okay=True, resolve_path=True, readable=True, dir_okay=False
26
- ),
27
- required=True,
28
- )
29
- @click.option(
30
- "--purpose",
31
- type=str,
32
- default=FilePurpose.FineTune.value,
33
- help="Purpose of file upload. Acceptable values in enum `seekrai.types.FilePurpose`. Defaults to `fine-tunes`.",
34
- )
35
- def upload(ctx: click.Context, file: pathlib.Path, purpose: str) -> None:
36
- """Upload file"""
37
-
38
- client: SeekrFlow = ctx.obj
39
-
40
- response = client.files.upload(file=file, purpose=purpose)
41
-
42
- click.echo(json.dumps(response.model_dump(), indent=4))
43
-
44
-
45
- @files.command()
46
- @click.pass_context
47
- def list(ctx: click.Context) -> None:
48
- """List files"""
49
- client: SeekrFlow = ctx.obj
50
-
51
- response = client.files.list()
52
-
53
- display_list = []
54
- for i in response.data or []:
55
- display_list.append(
56
- {
57
- "File name": "\n".join(wrap(i.filename or "", width=30)),
58
- "File ID": i.id,
59
- "Size": convert_bytes(
60
- float(str(i.bytes))
61
- ), # convert to string for mypy typing
62
- "Created At": convert_unix_timestamp(i.created_at or 0),
63
- "Line Count": i.line_count,
64
- }
65
- )
66
- table = tabulate(display_list, headers="keys", tablefmt="grid", showindex=True)
67
-
68
- click.echo(table)
69
-
70
-
71
- @files.command()
72
- @click.pass_context
73
- @click.argument("id", type=str, required=True)
74
- def retrieve(ctx: click.Context, id: str) -> None:
75
- """Upload file"""
76
-
77
- client: SeekrFlow = ctx.obj
78
-
79
- response = client.files.retrieve(id=id)
80
-
81
- click.echo(json.dumps(response.model_dump(), indent=4))
82
-
83
-
84
- @files.command()
85
- @click.pass_context
86
- @click.argument("id", type=str, required=True)
87
- @click.option("--output", type=str, default=None, help="Output filename")
88
- def retrieve_content(ctx: click.Context, id: str, output: str) -> None:
89
- """Retrieve file content and output to file"""
90
-
91
- client: SeekrFlow = ctx.obj
92
-
93
- response = client.files.retrieve_content(id=id, output=output)
94
-
95
- click.echo(json.dumps(response.model_dump(), indent=4))
96
-
97
-
98
- @files.command()
99
- @click.pass_context
100
- @click.argument("id", type=str, required=True)
101
- def delete(ctx: click.Context, id: str) -> None:
102
- """Delete remote file"""
103
-
104
- client: SeekrFlow = ctx.obj
105
-
106
- response = client.files.delete(id=id)
107
-
108
- click.echo(json.dumps(response.model_dump(), indent=4))
109
-
110
-
111
- @files.command()
112
- @click.pass_context
113
- @click.argument(
114
- "file",
115
- type=click.Path(
116
- exists=True, file_okay=True, resolve_path=True, readable=True, dir_okay=False
117
- ),
118
- required=True,
119
- )
120
- def check(ctx: click.Context, file: pathlib.Path) -> None:
121
- """Check file for issues"""
122
-
123
- report = check_file(file)
124
-
125
- click.echo(json.dumps(report, indent=4))
@@ -1,175 +0,0 @@
1
- import json
2
- from textwrap import wrap
3
-
4
- import click
5
- from tabulate import tabulate
6
-
7
- from seekrai import seekrflow
8
- from seekrai.utils import finetune_price_to_dollars, parse_timestamp
9
-
10
-
11
- @click.group(name="fine-tuning")
12
- @click.pass_context
13
- def fine_tuning(ctx: click.Context) -> None:
14
- """Fine-tunes API commands"""
15
- pass
16
-
17
-
18
- @fine_tuning.command()
19
- @click.pass_context
20
- @click.option(
21
- "--training-file", type=str, required=True, help="Training file ID from Files API"
22
- )
23
- @click.option("--model", type=str, required=True, help="Base model name")
24
- @click.option("--n-epochs", type=int, default=1, help="Number of epochs to train for")
25
- @click.option(
26
- "--n-checkpoints", type=int, default=1, help="Number of checkpoints to save"
27
- )
28
- @click.option("--batch-size", type=int, default=32, help="Train batch size")
29
- @click.option("--learning-rate", type=float, default=3e-5, help="Learning rate")
30
- @click.option(
31
- "--suffix", type=str, default=None, help="Suffix for the fine-tuned model name"
32
- )
33
- @click.option("--wandb-api-key", type=str, default=None, help="Wandb API key")
34
- def create(
35
- ctx: click.Context,
36
- training_file: str,
37
- model: str,
38
- n_epochs: int,
39
- n_checkpoints: int,
40
- batch_size: int,
41
- learning_rate: float,
42
- suffix: str,
43
- wandb_api_key: str,
44
- ) -> None:
45
- """Start fine-tuning"""
46
- client: SeekrFlow = ctx.obj
47
-
48
- response = client.fine_tuning.create(
49
- training_file=training_file,
50
- model=model,
51
- n_epochs=n_epochs,
52
- n_checkpoints=n_checkpoints,
53
- batch_size=batch_size,
54
- learning_rate=learning_rate,
55
- suffix=suffix,
56
- wandb_api_key=wandb_api_key,
57
- )
58
-
59
- click.echo(json.dumps(response.model_dump(), indent=4))
60
-
61
-
62
- @fine_tuning.command()
63
- @click.pass_context
64
- def list(ctx: click.Context) -> None:
65
- """List fine-tuning jobs"""
66
- client: SeekrFlow = ctx.obj
67
-
68
- response = client.fine_tuning.list()
69
-
70
- response.data = response.data or []
71
-
72
- response.data.sort(key=lambda x: parse_timestamp(x.created_at or ""))
73
-
74
- display_list = []
75
- for i in response.data:
76
- display_list.append(
77
- {
78
- "Fine-tune ID": i.id,
79
- "Model Output Name": "\n".join(wrap(i.output_name or "", width=30)),
80
- "Status": i.status,
81
- "Created At": i.created_at,
82
- "Price": f"""${finetune_price_to_dollars(
83
- float(str(i.total_price))
84
- )}""", # convert to string for mypy typing
85
- }
86
- )
87
- table = tabulate(display_list, headers="keys", tablefmt="grid", showindex=True)
88
-
89
- click.echo(table)
90
-
91
-
92
- @fine_tuning.command()
93
- @click.pass_context
94
- @click.argument("fine_tune_id", type=str, required=True)
95
- def retrieve(ctx: click.Context, fine_tune_id: str) -> None:
96
- """Retrieve fine-tuning job details"""
97
- client: SeekrFlow = ctx.obj
98
-
99
- response = client.fine_tuning.retrieve(fine_tune_id)
100
-
101
- # remove events from response for cleaner output
102
- response.events = None
103
-
104
- click.echo(json.dumps(response.model_dump(), indent=4))
105
-
106
-
107
- @fine_tuning.command()
108
- @click.pass_context
109
- @click.argument("fine_tune_id", type=str, required=True)
110
- def cancel(ctx: click.Context, fine_tune_id: str) -> None:
111
- """Cancel fine-tuning job"""
112
- client: SeekrFlow = ctx.obj
113
-
114
- response = client.fine_tuning.cancel(fine_tune_id)
115
-
116
- click.echo(json.dumps(response.model_dump(), indent=4))
117
-
118
-
119
- @fine_tuning.command()
120
- @click.pass_context
121
- @click.argument("fine_tune_id", type=str, required=True)
122
- def list_events(ctx: click.Context, fine_tune_id: str) -> None:
123
- """List fine-tuning events"""
124
- client: SeekrFlow = ctx.obj
125
-
126
- response = client.fine_tuning.list_events(fine_tune_id)
127
-
128
- response.data = response.data or []
129
-
130
- display_list = []
131
- for i in response.data:
132
- display_list.append(
133
- {
134
- "Message": "\n".join(wrap(i.message or "", width=50)),
135
- "Type": i.type,
136
- "Created At": parse_timestamp(i.created_at or ""),
137
- "Hash": i.hash,
138
- }
139
- )
140
- table = tabulate(display_list, headers="keys", tablefmt="grid", showindex=True)
141
-
142
- click.echo(table)
143
-
144
-
145
- @fine_tuning.command()
146
- @click.pass_context
147
- @click.argument("fine_tune_id", type=str, required=True)
148
- @click.option(
149
- "--output_dir",
150
- type=click.Path(exists=True, file_okay=False, resolve_path=True),
151
- required=False,
152
- default=None,
153
- help="Output directory",
154
- )
155
- @click.option(
156
- "--checkpoint-step",
157
- type=int,
158
- required=False,
159
- default=-1,
160
- help="Download fine-tuning checkpoint. Defaults to latest.",
161
- )
162
- def download(
163
- ctx: click.Context,
164
- fine_tune_id: str,
165
- output_dir: str,
166
- checkpoint_step: int,
167
- ) -> None:
168
- """Download fine-tuning checkpoint"""
169
- client: SeekrFlow = ctx.obj
170
-
171
- response = client.fine_tuning.download(
172
- fine_tune_id, output=output_dir, checkpoint_step=checkpoint_step
173
- )
174
-
175
- click.echo(json.dumps(response.model_dump(), indent=4))
seekrai/cli/api/images.py DELETED
@@ -1,82 +0,0 @@
1
- import base64
2
- import pathlib
3
-
4
- import click
5
- from PIL import Image
6
-
7
- from seekrai import seekrflow
8
- from seekrai.types import ImageResponse
9
- from seekrai.types.images import ImageChoicesData
10
-
11
-
12
- @click.group()
13
- @click.pass_context
14
- def images(ctx: click.Context) -> None:
15
- """Images generations API commands"""
16
- pass
17
-
18
-
19
- @images.command()
20
- @click.pass_context
21
- @click.argument("prompt", type=str, required=True)
22
- @click.option("--model", type=str, required=True, help="Model name")
23
- @click.option("--steps", type=int, default=20, help="Number of steps to run generation")
24
- @click.option("--seed", type=int, default=None, help="Random seed")
25
- @click.option("--n", type=int, default=1, help="Number of images to generate")
26
- @click.option("--height", type=int, default=1024, help="Image height")
27
- @click.option("--width", type=int, default=1024, help="Image width")
28
- @click.option("--negative-prompt", type=str, default=None, help="Negative prompt")
29
- @click.option(
30
- "--output",
31
- type=click.Path(exists=True, file_okay=False, resolve_path=True),
32
- required=False,
33
- default=pathlib.Path("."),
34
- help="Output directory",
35
- )
36
- @click.option("--prefix", type=str, required=False, default="image-")
37
- @click.option("--no-show", is_flag=True, help="Do not open images in viewer")
38
- def generate(
39
- ctx: click.Context,
40
- prompt: str,
41
- model: str,
42
- steps: int,
43
- seed: int,
44
- n: int,
45
- height: int,
46
- width: int,
47
- negative_prompt: str,
48
- output: pathlib.Path,
49
- prefix: str,
50
- no_show: bool,
51
- ) -> None:
52
- """Generate image"""
53
-
54
- client: SeekrFlow = ctx.obj
55
-
56
- response = client.images.generate(
57
- prompt=prompt,
58
- model=model,
59
- steps=steps,
60
- seed=seed,
61
- n=n,
62
- height=height,
63
- width=width,
64
- negative_prompt=negative_prompt,
65
- )
66
-
67
- assert isinstance(response, ImageResponse)
68
- assert isinstance(response.data, list)
69
-
70
- for i, choice in enumerate(response.data):
71
- assert isinstance(choice, ImageChoicesData)
72
-
73
- with open(f"{output}/{prefix}{choice.index}.png", "wb") as f:
74
- f.write(base64.b64decode(choice.b64_json))
75
-
76
- click.echo(
77
- f"Image [{i + 1}/{len(response.data)}] saved to {output}/{prefix}{choice.index}.png"
78
- )
79
-
80
- if not no_show:
81
- image = Image.open(f"{output}/{prefix}{choice.index}.png")
82
- image.show()
seekrai/cli/api/models.py DELETED
@@ -1,42 +0,0 @@
1
- from textwrap import wrap
2
-
3
- import click
4
- from tabulate import tabulate
5
-
6
- from seekrai import seekrflow
7
- from seekrai.types.models import ModelObject
8
-
9
-
10
- @click.group()
11
- @click.pass_context
12
- def models(ctx: click.Context) -> None:
13
- """Models API commands"""
14
- pass
15
-
16
-
17
- @models.command()
18
- @click.pass_context
19
- def list(ctx: click.Context) -> None:
20
- """List models"""
21
- client: SeekrFlow = ctx.obj
22
-
23
- response = client.models.list()
24
-
25
- display_list = []
26
-
27
- model: ModelObject
28
- for model in response:
29
- display_list.append(
30
- {
31
- "ID": "\n".join(wrap(model.id or "", width=30)),
32
- "Name": "\n".join(wrap(model.display_name or "", width=30)),
33
- "Organization": model.organization,
34
- "Type": model.type,
35
- "Context Length": model.context_length,
36
- "License": "\n".join(wrap(model.license or "", width=30)),
37
- "Input per 1M token": model.pricing.input,
38
- "Output per 1M token": model.pricing.output,
39
- }
40
- )
41
-
42
- click.echo(tabulate(display_list, headers="keys", tablefmt="grid"))
seekrai/cli/cli.py DELETED
@@ -1,77 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import os
4
- from typing import Any
5
-
6
- import click
7
-
8
- import seekrai
9
- from seekrai.cli.api.chat import chat, interactive
10
- from seekrai.cli.api.completions import completions
11
- from seekrai.cli.api.files import files
12
- from seekrai.cli.api.finetune import fine_tuning
13
- from seekrai.cli.api.images import images
14
- from seekrai.cli.api.models import models
15
- from seekrai.constants import MAX_RETRIES, TIMEOUT_SECS
16
-
17
-
18
- def print_version(ctx: click.Context, params: Any, value: Any) -> None:
19
- if not value or ctx.resilient_parsing:
20
- return
21
- click.echo(f"Version {seekrai.version}")
22
- ctx.exit()
23
-
24
-
25
- @click.group()
26
- @click.pass_context
27
- @click.option(
28
- "--api-key",
29
- type=str,
30
- help="API Key. Defaults to environment variable `SEEKRFLOW_API_KEY`",
31
- default=os.getenv("SEEKRFLOW_API_KEY"),
32
- )
33
- @click.option(
34
- "--base-url", type=str, help="API Base URL. Defaults to SeekrFlow AI endpoint."
35
- )
36
- @click.option(
37
- "--timeout", type=int, help=f"Request timeout. Defaults to {TIMEOUT_SECS} seconds"
38
- )
39
- @click.option(
40
- "--max-retries",
41
- type=int,
42
- help=f"Maximum number of HTTP retries. Defaults to {MAX_RETRIES}.",
43
- )
44
- @click.option(
45
- "--version",
46
- is_flag=True,
47
- callback=print_version,
48
- expose_value=False,
49
- is_eager=True,
50
- help="Print version",
51
- )
52
- @click.option("--debug", help="Debug mode", is_flag=True)
53
- def main(
54
- ctx: click.Context,
55
- api_key: str | None,
56
- base_url: str | None,
57
- timeout: int | None,
58
- max_retries: int | None,
59
- debug: bool | None,
60
- ) -> None:
61
- """This is a sample CLI tool."""
62
- seekrai.log = "debug" if debug else None
63
- ctx.obj = seekrai.SeekrFlow(
64
- api_key=api_key, base_url=base_url, timeout=timeout, max_retries=max_retries
65
- )
66
-
67
-
68
- main.add_command(chat)
69
- main.add_command(interactive)
70
- main.add_command(completions)
71
- main.add_command(images)
72
- main.add_command(files)
73
- main.add_command(fine_tuning)
74
- main.add_command(models)
75
-
76
- if __name__ == "__main__":
77
- main()
File without changes
seekrai/legacy/base.py DELETED
@@ -1,27 +0,0 @@
1
- import functools
2
- import warnings
3
-
4
-
5
- API_KEY_WARNING = (
6
- "The use of seekrai.api_key is deprecated and will be removed in the next major release. "
7
- "Please set the SEEKRFLOW_API_KEY environment variable instead."
8
- )
9
-
10
-
11
- def deprecated(func): # type: ignore
12
- """
13
- This is a decorator which can be used to mark functions
14
- as deprecated. It will result in a warning being emitted
15
- when the function is used.
16
- """
17
-
18
- @functools.wraps(func)
19
- def new_func(*args, **kwargs): # type: ignore
20
- warnings.warn(
21
- f"Call to deprecated function {func.__name__}.",
22
- category=DeprecationWarning,
23
- stacklevel=2,
24
- )
25
- return func(*args, **kwargs)
26
-
27
- return new_func
@@ -1,91 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import warnings
4
- from typing import Any, AsyncGenerator, Dict, Iterator
5
-
6
- import seekrai
7
- from seekrai.legacy.base import API_KEY_WARNING, deprecated
8
- from seekrai.types import CompletionChunk, CompletionResponse
9
-
10
-
11
- class Complete:
12
- @classmethod
13
- @deprecated # type: ignore
14
- def create(
15
- cls,
16
- prompt: str,
17
- **kwargs,
18
- ) -> Dict[str, Any]:
19
- """Legacy completion function."""
20
-
21
- api_key = None
22
- if seekrai.api_key:
23
- warnings.warn(API_KEY_WARNING)
24
- api_key = seekrai.api_key
25
-
26
- client = seekrai.SeekrFlow(api_key=api_key)
27
-
28
- return client.completions.create(
29
- prompt=prompt, stream=False, **kwargs
30
- ).model_dump() # type: ignore
31
-
32
- @classmethod
33
- @deprecated # type: ignore
34
- def create_streaming(
35
- cls,
36
- prompt: str,
37
- **kwargs,
38
- ) -> Iterator[Dict[str, Any]]:
39
- """Legacy streaming completion function."""
40
-
41
- api_key = None
42
- if seekrai.api_key:
43
- warnings.warn(API_KEY_WARNING)
44
- api_key = seekrai.api_key
45
-
46
- client = seekrai.SeekrFlow(api_key=api_key)
47
-
48
- return (
49
- token.model_dump() # type: ignore
50
- for token in client.completions.create(prompt=prompt, stream=True, **kwargs)
51
- )
52
-
53
-
54
- class Completion:
55
- @classmethod
56
- @deprecated # type: ignore
57
- def create(
58
- cls,
59
- prompt: str,
60
- **kwargs,
61
- ) -> CompletionResponse | Iterator[CompletionChunk]:
62
- """Completion function."""
63
-
64
- api_key = None
65
- if seekrai.api_key:
66
- warnings.warn(API_KEY_WARNING)
67
- api_key = seekrai.api_key
68
-
69
- client = seekrai.SeekrFlow(api_key=api_key)
70
-
71
- return client.completions.create(prompt=prompt, **kwargs)
72
-
73
-
74
- class AsyncComplete:
75
- @classmethod
76
- @deprecated # type: ignore
77
- async def create(
78
- cls,
79
- prompt: str,
80
- **kwargs,
81
- ) -> CompletionResponse | AsyncGenerator[CompletionChunk, None]:
82
- """Async completion function."""
83
-
84
- api_key = None
85
- if seekrai.api_key:
86
- warnings.warn(API_KEY_WARNING)
87
- api_key = seekrai.api_key
88
-
89
- client = seekrai.AsyncSeekrFlow(api_key=api_key)
90
-
91
- return await client.completions.create(prompt=prompt, **kwargs)
@@ -1,25 +0,0 @@
1
- import warnings
2
- from typing import Any, Dict
3
-
4
- import seekrai
5
- from seekrai.legacy.base import API_KEY_WARNING, deprecated
6
-
7
-
8
- class Embeddings:
9
- @classmethod
10
- @deprecated # type: ignore
11
- def create(
12
- cls,
13
- input: str,
14
- **kwargs,
15
- ) -> Dict[str, Any]:
16
- """Legacy embeddings function."""
17
-
18
- api_key = None
19
- if seekrai.api_key:
20
- warnings.warn(API_KEY_WARNING)
21
- api_key = seekrai.api_key
22
-
23
- client = seekrai.SeekrFlow(api_key=api_key)
24
-
25
- return client.embeddings.create(input=input, **kwargs).model_dump()