File size: 3,674 Bytes
9d614f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
"""Fallback interactive CLI chat (PRIVATE to Serving_Module) - used when TELEGRAM_BOT_TOKEN is empty.

Commands
  mode thinking | mode non_thinking | mode max_thinking     switch the answer mode
  teach: सवाल | जवाब                                        teach the model a fact right now
  clear                                                      forget the conversation so far
  help                                                       show this list
  exit | quit                                                leave
"""
from __future__ import annotations

import re
import sys

from .inference_engine import MODES, InferenceEngine, normalise_mode

HELP = __doc__.split("Commands", 1)[1].strip("\n")


def _split_teach(text: str):
    body = text.split(":", 1)[1] if ":" in text else ""
    if "|" not in body:
        return None, None
    question, _, answer = body.partition("|")
    return question.strip(), answer.strip()


def _read_line(out, mode: str) -> str:
    out.write(f"\n[{mode}] आप> ")
    out.flush()
    line = sys.stdin.readline()
    if line == "":
        raise EOFError
    return line


def run_cli(engine: InferenceEngine, start_mode: str = "non_thinking", stream_out=None) -> None:
    out = stream_out or sys.stdout
    mode = normalise_mode(start_mode) or "non_thinking"

    def say(text: str = "", end: str = "\n") -> None:
        out.write(text + end)
        out.flush()

    say("\n" + "=" * 68)
    say(" RSS AI  -  interactive chat   (type 'help' for commands, 'exit' to leave)")
    say(f" current mode: {mode}   |   modes: {', '.join(MODES)}")
    say("=" * 68)
    while True:
        try:
            line = input(f"\n[{mode}] आप> ") if stream_out is None else _read_line(out, mode)
        except EOFError:                                     # pipe closed / input stream ended
            say("\n(input closed - bye)")
            return
        except KeyboardInterrupt:
            say("\nbye!")
            return
        text = line.strip()
        if not text:
            continue
        low = text.lower()
        if low in ("exit", "quit", "/exit", "/quit", "q"):
            say("bye!")
            return
        if low in ("help", "/help", "?"):
            say(HELP)
            continue
        if low in ("clear", "/clear"):
            engine.reset()
            say("conversation cleared.")
            continue
        if low.startswith(("mode ", "/mode ")):
            chosen = normalise_mode(text.split(None, 1)[1])
            if chosen:
                mode = chosen
                say(f"mode -> {mode}")
            else:
                say(f"unknown mode. choose one of: {', '.join(MODES)}")
            continue
        if low.startswith("/") and low.lstrip("/") in MODES:       # '/thinking' style shortcut
            mode = low.lstrip("/")
            say(f"mode -> {mode}")
            continue
        if re.match(r"teach\s*:", low):
            question, answer = _split_teach(text)
            if question is None:
                say("format:  teach: सवाल | जवाब")
            else:
                say(engine.teach(question, answer))
            continue
        try:
            say("RSS AI> ", end="")
            result = engine.generate(text, mode=mode, on_text=lambda chunk: say(chunk, end=""))
            say(f"\n   ({result['mode']}, {result['tokens']} tokens, {result['seconds']}s, from {result['source']})")
        except KeyboardInterrupt:
            say("\n   (generation interrupted)")
        except Exception as exc:                              # never crash the chat loop
            say(f"\n   error: {type(exc).__name__}: {exc}")