anon334test commited on
Commit
f85e4e5
·
verified ·
1 Parent(s): 0ae4e50

Add enable_thinking chat template, auto threads; true fast mode

Browse files
Files changed (3) hide show
  1. Dockerfile +2 -3
  2. app.py +11 -4
  3. chat_template.jinja +90 -0
Dockerfile CHANGED
@@ -4,9 +4,7 @@ FROM python:3.11-slim
4
  ENV DEBIAN_FRONTEND=noninteractive \
5
  PYTHONUNBUFFERED=1 \
6
  HF_HOME=/home/user/.cache/huggingface \
7
- HF_HUB_ENABLE_HF_TRANSFER=1 \
8
- NUM_THREADS=2 \
9
- OMP_NUM_THREADS=2
10
 
11
  RUN apt-get update && apt-get install -y --no-install-recommends \
12
  curl ca-certificates libgomp1 \
@@ -32,6 +30,7 @@ RUN pip install --no-cache-dir \
32
 
33
  WORKDIR /home/user/app
34
  COPY app.py .
 
35
  RUN chown -R user:user /home/user
36
 
37
  USER user
 
4
  ENV DEBIAN_FRONTEND=noninteractive \
5
  PYTHONUNBUFFERED=1 \
6
  HF_HOME=/home/user/.cache/huggingface \
7
+ HF_HUB_ENABLE_HF_TRANSFER=1
 
 
8
 
9
  RUN apt-get update && apt-get install -y --no-install-recommends \
10
  curl ca-certificates libgomp1 \
 
30
 
31
  WORKDIR /home/user/app
32
  COPY app.py .
33
+ COPY chat_template.jinja .
34
  RUN chown -R user:user /home/user
35
 
36
  USER user
app.py CHANGED
@@ -13,8 +13,12 @@ GGUF_FILE = os.environ.get("GGUF_FILE", "Qwen3.5-0.8B.Q4_K_M.gguf")
13
  HF_TOKEN = os.environ.get("HF_TOKEN") # optional; model is public
14
  PORT = int(os.environ.get("PORT", "7860"))
15
  LLAMA_PORT = int(os.environ.get("LLAMA_PORT", "8080"))
16
- NUM_THREADS = os.environ.get("NUM_THREADS", "2")
 
17
  BIN = "/opt/llamabin"
 
 
 
18
  LLAMA = f"http://127.0.0.1:{LLAMA_PORT}"
19
  # Qwen3.5-0.8B native context = 262144. On CPU-basic we keep a smaller window for fast
20
  # startup + low memory; raise N_CTX via a Space variable if you need long context.
@@ -42,11 +46,14 @@ def start_llama(model_path):
42
  "-m", model_path, "--host", "127.0.0.1", "--port", str(LLAMA_PORT),
43
  "-c", N_CTX, "-t", NUM_THREADS, "-b", "256", "--no-mmap",
44
  "--parallel", os.environ.get("PARALLEL", "1"),
45
- # Use the model's OWN embedded chat template (Qwen3.5 ChatML). No injection.
46
  "--jinja",
47
- # Separate the <think> chain-of-thought into reasoning_content so the answer stays clean.
48
- "--reasoning-format", "auto",
49
  ]
 
 
 
 
 
50
  # Optional extra flags (e.g. "-fa on") via LLAMA_EXTRA_ARGS, space separated.
51
  extra = os.environ.get("LLAMA_EXTRA_ARGS", "").split()
52
  if extra:
 
13
  HF_TOKEN = os.environ.get("HF_TOKEN") # optional; model is public
14
  PORT = int(os.environ.get("PORT", "7860"))
15
  LLAMA_PORT = int(os.environ.get("LLAMA_PORT", "8080"))
16
+ # Use every available core by default (cpu-basic = 2 vCPU); override with NUM_THREADS.
17
+ NUM_THREADS = os.environ.get("NUM_THREADS") or str(os.cpu_count() or 2)
18
  BIN = "/opt/llamabin"
19
+ # Custom chat template that adds an enable_thinking toggle (the model's own template
20
+ # ALWAYS opens a <think> block; this lets "Fast (no thinking)" actually skip reasoning).
21
+ CHAT_TEMPLATE_FILE = os.environ.get("CHAT_TEMPLATE_FILE", "/home/user/app/chat_template.jinja")
22
  LLAMA = f"http://127.0.0.1:{LLAMA_PORT}"
23
  # Qwen3.5-0.8B native context = 262144. On CPU-basic we keep a smaller window for fast
24
  # startup + low memory; raise N_CTX via a Space variable if you need long context.
 
46
  "-m", model_path, "--host", "127.0.0.1", "--port", str(LLAMA_PORT),
47
  "-c", N_CTX, "-t", NUM_THREADS, "-b", "256", "--no-mmap",
48
  "--parallel", os.environ.get("PARALLEL", "1"),
49
+ # Apply our chat template (adds enable_thinking toggle for true fast mode).
50
  "--jinja",
 
 
51
  ]
52
+ if CHAT_TEMPLATE_FILE and os.path.exists(CHAT_TEMPLATE_FILE):
53
+ cmd += ["--chat-template-file", CHAT_TEMPLATE_FILE]
54
+ # Separate the <think> chain-of-thought into reasoning_content so the answer stays clean.
55
+ cmd += ["--reasoning-format", "auto"]
56
+ print(f"[init] cpu_count={os.cpu_count()} threads={NUM_THREADS}", flush=True)
57
  # Optional extra flags (e.g. "-fa on") via LLAMA_EXTRA_ARGS, space separated.
58
  extra = os.environ.get("LLAMA_EXTRA_ARGS", "").split()
59
  if extra:
chat_template.jinja ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {%- if tools %}
2
+ {{- '<|im_start|>system\n' }}
3
+ {%- if messages[0].role == 'system' %}
4
+ {{- messages[0].content + '\n\n' }}
5
+ {%- endif %}
6
+ {{- "# Tools\n\nYou may call one or more functions to assist with the user query.\n\nYou are provided with function signatures within <tools></tools> XML tags:\n<tools>" }}
7
+ {%- for tool in tools %}
8
+ {{- "\n" }}
9
+ {{- tool | tojson }}
10
+ {%- endfor %}
11
+ {{- "\n</tools>\n\nFor each function call, return a json object with function name and arguments within <tool_call></tool_call> XML tags:\n<tool_call>\n{\"name\": <function-name>, \"arguments\": <args-json-object>}\n</tool_call><|im_end|>\n" }}
12
+ {%- else %}
13
+ {%- if messages[0].role == 'system' %}
14
+ {{- '<|im_start|>system\n' + messages[0].content + '<|im_end|>\n' }}
15
+ {%- endif %}
16
+ {%- endif %}
17
+ {%- set ns = namespace(multi_step_tool=true, last_query_index=messages|length - 1) %}
18
+ {%- for message in messages[::-1] %}
19
+ {%- set index = (messages|length - 1) - loop.index0 %}
20
+ {%- if ns.multi_step_tool and message.role == "user" and message.content is string and not(message.content.startswith('<tool_response>') and message.content.endswith('</tool_response>')) %}
21
+ {%- set ns.multi_step_tool = false %}
22
+ {%- set ns.last_query_index = index %}
23
+ {%- endif %}
24
+ {%- endfor %}
25
+ {%- for message in messages %}
26
+ {%- if message.content is string %}
27
+ {%- set content = message.content %}
28
+ {%- else %}
29
+ {%- set content = '' %}
30
+ {%- endif %}
31
+ {%- if (message.role == "user") or (message.role == "system" and not loop.first) %}
32
+ {{- '<|im_start|>' + message.role + '\n' + content + '<|im_end|>' + '\n' }}
33
+ {%- elif message.role == "assistant" %}
34
+ {%- set reasoning_content = '' %}
35
+ {%- if message.reasoning_content is string %}
36
+ {%- set reasoning_content = message.reasoning_content %}
37
+ {%- else %}
38
+ {%- if '</think>' in content %}
39
+ {%- set reasoning_content = content.split('</think>')[0].rstrip('\n').split('<think>')[-1].lstrip('\n') %}
40
+ {%- set content = content.split('</think>')[-1].lstrip('\n') %}
41
+ {%- endif %}
42
+ {%- endif %}
43
+ {%- if loop.index0 > ns.last_query_index %}
44
+ {%- if loop.last or (not loop.last and reasoning_content) %}
45
+ {{- '<|im_start|>' + message.role + '\n<think>\n' + reasoning_content.strip('\n') + '\n</think>\n\n' + content.lstrip('\n') }}
46
+ {%- else %}
47
+ {{- '<|im_start|>' + message.role + '\n' + content }}
48
+ {%- endif %}
49
+ {%- else %}
50
+ {{- '<|im_start|>' + message.role + '\n' + content }}
51
+ {%- endif %}
52
+ {%- if message.tool_calls %}
53
+ {%- for tool_call in message.tool_calls %}
54
+ {%- if (loop.first and content) or (not loop.first) %}
55
+ {{- '\n' }}
56
+ {%- endif %}
57
+ {%- if tool_call.function %}
58
+ {%- set tool_call = tool_call.function %}
59
+ {%- endif %}
60
+ {{- '<tool_call>\n{"name": "' }}
61
+ {{- tool_call.name }}
62
+ {{- '", "arguments": ' }}
63
+ {%- if tool_call.arguments is string %}
64
+ {{- tool_call.arguments }}
65
+ {%- else %}
66
+ {{- tool_call.arguments | tojson }}
67
+ {%- endif %}
68
+ {{- '}\n</tool_call>' }}
69
+ {%- endfor %}
70
+ {%- endif %}
71
+ {{- '<|im_end|>\n' }}
72
+ {%- elif message.role == "tool" %}
73
+ {%- if loop.first or (messages[loop.index0 - 1].role != "tool") %}
74
+ {{- '<|im_start|>user' }}
75
+ {%- endif %}
76
+ {{- '\n<tool_response>\n' }}
77
+ {{- content }}
78
+ {{- '\n</tool_response>' }}
79
+ {%- if loop.last or (messages[loop.index0 + 1].role != "tool") %}
80
+ {{- '<|im_end|>\n' }}
81
+ {%- endif %}
82
+ {%- endif %}
83
+ {%- endfor %}
84
+ {%- if add_generation_prompt %}
85
+ {%- if enable_thinking is defined and enable_thinking is false %}
86
+ {{- '<|im_start|>assistant\n<think>\n\n</think>\n\n' }}
87
+ {%- else %}
88
+ {{- '<|im_start|>assistant\n<think>\n' }}
89
+ {%- endif %}
90
+ {%- endif %}