cli.py 2.75 KB
Newer Older
Michael Yang's avatar
Michael Yang committed
1
import os
Michael Yang's avatar
Michael Yang committed
2
import sys
Michael Yang's avatar
Michael Yang committed
3
4
5
6
7
8
9
10
11
12
import json
from pathlib import Path
from argparse import ArgumentParser

from ollama import model, engine
from ollama.cmd import server


def main():
    parser = ArgumentParser()
Bruce MacDonald's avatar
Bruce MacDonald committed
13
    parser.add_argument("--models-home", default=Path.home() / ".ollama" / "models")
Michael Yang's avatar
Michael Yang committed
14
15
16

    subparsers = parser.add_subparsers()

Bruce MacDonald's avatar
Bruce MacDonald committed
17
    server.set_parser(subparsers.add_parser("serve"))
Michael Yang's avatar
Michael Yang committed
18

Bruce MacDonald's avatar
Bruce MacDonald committed
19
    list_parser = subparsers.add_parser("list")
Michael Yang's avatar
Michael Yang committed
20
    list_parser.set_defaults(fn=list_models)
Michael Yang's avatar
Michael Yang committed
21

Bruce MacDonald's avatar
Bruce MacDonald committed
22
23
    generate_parser = subparsers.add_parser("generate")
    generate_parser.add_argument("model")
Michael Yang's avatar
Michael Yang committed
24
    generate_parser.add_argument("prompt", nargs="?")
Michael Yang's avatar
Michael Yang committed
25
26
    generate_parser.set_defaults(fn=generate)

Bruce MacDonald's avatar
Bruce MacDonald committed
27
    add_parser = subparsers.add_parser("add")
Michael Yang's avatar
Michael Yang committed
28
    add_parser.add_argument("model")
Bruce MacDonald's avatar
Bruce MacDonald committed
29
    add_parser.set_defaults(fn=add)
Bruce MacDonald's avatar
Bruce MacDonald committed
30

Bruce MacDonald's avatar
Bruce MacDonald committed
31
    pull_parser = subparsers.add_parser("pull")
Bruce MacDonald's avatar
Bruce MacDonald committed
32
    pull_parser.add_argument("model")
Bruce MacDonald's avatar
Bruce MacDonald committed
33
34
    pull_parser.set_defaults(fn=pull)

Bruce MacDonald's avatar
Bruce MacDonald committed
35
36
37
38
    pull_parser = subparsers.add_parser("run")
    pull_parser.add_argument("model")
    pull_parser.set_defaults(fn=run)

Michael Yang's avatar
Michael Yang committed
39
40
41
    args = parser.parse_args()
    args = vars(args)

Michael Yang's avatar
Michael Yang committed
42
43
44
    try:
        fn = args.pop("fn")
        fn(**args)
Michael Yang's avatar
Michael Yang committed
45
46
    except KeyboardInterrupt:
        pass
Michael Yang's avatar
Michael Yang committed
47
48
49
50
    except KeyError:
        parser.print_help()
    except Exception as e:
        print(e)
Michael Yang's avatar
Michael Yang committed
51
52


Michael Yang's avatar
Michael Yang committed
53
def list_models(*args, **kwargs):
Michael Yang's avatar
Michael Yang committed
54
55
56
57
58
    for m in model.models(*args, **kwargs):
        print(m)


def generate(*args, **kwargs):
Bruce MacDonald's avatar
Bruce MacDonald committed
59
60
    if prompt := kwargs.get("prompt"):
        print(">>>", prompt, flush=True)
Michael Yang's avatar
Michael Yang committed
61
62
63
        generate_oneshot(*args, **kwargs)
        return

Michael Yang's avatar
Michael Yang committed
64
65
66
67
    if sys.stdin.isatty():
        return generate_interactive(*args, **kwargs)

    return generate_batch(*args, **kwargs)
Michael Yang's avatar
Michael Yang committed
68
69
70


def generate_oneshot(*args, **kwargs):
Michael Yang's avatar
Michael Yang committed
71
72
    print(flush=True)

Michael Yang's avatar
Michael Yang committed
73
74
    for output in engine.generate(*args, **kwargs):
        output = json.loads(output)
Bruce MacDonald's avatar
Bruce MacDonald committed
75
        choices = output.get("choices", [])
Michael Yang's avatar
Michael Yang committed
76
        if len(choices) > 0:
Michael Yang's avatar
Michael Yang committed
77
78
            print(choices[0].get("text", ""), end="", flush=True)

79
    # end with a new line
Michael Yang's avatar
Michael Yang committed
80
81
    print(flush=True)
    print(flush=True)
Michael Yang's avatar
Michael Yang committed
82
83
84


def generate_interactive(*args, **kwargs):
Michael Yang's avatar
Michael Yang committed
85
    while True:
Bruce MacDonald's avatar
Bruce MacDonald committed
86
        print(">>> ", end="", flush=True)
Michael Yang's avatar
Michael Yang committed
87
88
89
        line = next(sys.stdin)
        if not line:
            return
Michael Yang's avatar
Michael Yang committed
90

Michael Yang's avatar
Michael Yang committed
91
92
93
94
95
96
        kwargs.update({"prompt": line})
        generate_oneshot(*args, **kwargs)


def generate_batch(*args, **kwargs):
    for line in sys.stdin:
Bruce MacDonald's avatar
Bruce MacDonald committed
97
        print(">>> ", line, end="", flush=True)
Michael Yang's avatar
Michael Yang committed
98
        kwargs.update({"prompt": line})
Michael Yang's avatar
Michael Yang committed
99
        generate_oneshot(*args, **kwargs)
Bruce MacDonald's avatar
Bruce MacDonald committed
100
101


Michael Yang's avatar
Michael Yang committed
102
103
def add(model, models_home):
    os.rename(model, Path(models_home) / Path(model).name)
Bruce MacDonald's avatar
Bruce MacDonald committed
104
105
106
107


def pull(*args, **kwargs):
    model.pull(*args, **kwargs)
Bruce MacDonald's avatar
Bruce MacDonald committed
108
109
110
111
112
113
114


def run(*args, **kwargs):
    name = model.pull(*args, **kwargs)
    kwargs.update({"model": name})
    print(f"Running {name}...")
    generate(*args, **kwargs)