peninsula123 commited on
Commit
bce1d4b
·
1 Parent(s): a1231c7

feat(main): finish backend

Browse files
Files changed (3) hide show
  1. app.py +7 -0
  2. open_cortex/ui/app.py +138 -0
  3. pyproject.toml +3 -0
app.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from open_cortex.ui.app import build_app
2
+
3
+ demo = build_app()
4
+
5
+ if __name__ == "__main__":
6
+ demo.queue()
7
+ demo.launch()
open_cortex/ui/app.py CHANGED
@@ -0,0 +1,138 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from open_cortex.ui.gradio_history import history_to_chat_messages
3
+ from open_cortex.runtime.client import stream_chat_events
4
+
5
+
6
+ def format_runtime(event) -> str:
7
+ if event.kind == "request_started":
8
+ return "Phase: request started\nWaiting for first token..."
9
+
10
+ if event.kind == "first_token" and event.snapshot is not None:
11
+ snapshot = event.snapshot
12
+ context_tokens = (
13
+ snapshot.slot_context_tokens[0]
14
+ if snapshot.slot_context_tokens
15
+ else None
16
+ )
17
+
18
+ return "\n".join(
19
+ [
20
+ "Phase: first token",
21
+ f"TTFT: {event.ttft_ms:.1f} ms",
22
+ f"Context: {context_tokens} / {snapshot.slot_context_size}",
23
+ f"Token Stream: {snapshot.decode_tps} tok/s",
24
+ (
25
+ "Engine: "
26
+ f"processing={snapshot.requests_processing} "
27
+ f"deferred={snapshot.requests_deferred}"
28
+ ),
29
+ ]
30
+ )
31
+
32
+ if event.kind == "request_completed":
33
+ return "\n".join(
34
+ [
35
+ "Phase: completed",
36
+ f"Prompt tokens: {event.prompt_tokens}",
37
+ f"Output tokens: {event.completion_tokens}",
38
+ f"Prefill: {event.prompt_tps:.1f} tok/s",
39
+ f"Decode: {event.decode_tps:.1f} tok/s",
40
+ ]
41
+ )
42
+
43
+ return "Phase: decoding"
44
+
45
+
46
+
47
+ def user(user_message: str, history: list[dict]) -> tuple[str, list[dict]]:
48
+ if not user_message.strip():
49
+ return "", history
50
+
51
+ return "", history + [
52
+ {
53
+ "role": "user",
54
+ "content": user_message,
55
+ }
56
+ ]
57
+
58
+ def bot(history: list):
59
+ messages = history_to_chat_messages(history)
60
+
61
+ history.append(
62
+ {
63
+ "role": "assistant",
64
+ "content": "",
65
+ }
66
+ )
67
+
68
+ runtime_text = "Phase: idle"
69
+
70
+ for event in stream_chat_events(messages):
71
+ runtime_text = format_runtime(event)
72
+
73
+ if event.text_delta:
74
+ history[-1]["content"] += event.text_delta
75
+
76
+ yield history, runtime_text
77
+
78
+
79
+
80
+ def build_app() -> gr.Blocks:
81
+ with gr.Blocks() as demo:
82
+ gr.Markdown("# OpenCortex Minimal Chat")
83
+
84
+ with gr.Row():
85
+ with gr.Column(scale=2):
86
+ chatbot = gr.Chatbot(
87
+ height=480,
88
+ )
89
+ msg = gr.Textbox(
90
+ placeholder="Ask the local model...",
91
+ show_label=False,
92
+ )
93
+ clear = gr.Button("Clear")
94
+
95
+ with gr.Column(scale=1):
96
+ runtime = gr.Textbox(
97
+ label="Runtime",
98
+ value="Phase: idle",
99
+ lines=10,
100
+ interactive=False,
101
+ )
102
+
103
+
104
+ msg.submit(
105
+ user,
106
+ [msg, chatbot],
107
+ [msg, chatbot],
108
+ queue=False,
109
+ ).then(
110
+ bot,
111
+ chatbot,
112
+ [chatbot, runtime],
113
+ )
114
+
115
+ clear.click(
116
+ lambda: ([], "Phase: idle"),
117
+ None,
118
+ [chatbot, runtime],
119
+ queue=False,
120
+ )
121
+ return demo
122
+
123
+
124
+ def main() -> None:
125
+ demo = build_app()
126
+ demo.queue()
127
+ demo.launch()
128
+
129
+
130
+
131
+ if __name__ == "__main__":
132
+ main()
133
+
134
+
135
+
136
+
137
+
138
+
pyproject.toml CHANGED
@@ -21,3 +21,6 @@ dev = [
21
  [[tool.uv.index]]
22
  url = "https://pypi.tuna.tsinghua.edu.cn/simple"
23
  default = true
 
 
 
 
21
  [[tool.uv.index]]
22
  url = "https://pypi.tuna.tsinghua.edu.cn/simple"
23
  default = true
24
+
25
+ [project.scripts]
26
+ open-cortex = "open_cortex.ui.app:main"