Skip to content

Commit 90092d6

Browse files
committed
Merge branch 'master' of https://github.com/ggml-org/llama.cpp
2 parents 6d1b660 + c8ac02f commit 90092d6

167 files changed

Lines changed: 2360 additions & 11603 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/labeler.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,18 @@ android:
7373
- changed-files:
7474
- any-glob-to-any-file:
7575
- examples/llama.android/**
76+
server/webui:
77+
- changed-files:
78+
- any-glob-to-any-file:
79+
- tools/server/webui/**
80+
- tools/server/public/**
7681
server:
7782
- changed-files:
7883
- any-glob-to-any-file:
7984
- tools/server/**
85+
86+
87+
8088
ggml:
8189
- changed-files:
8290
- any-glob-to-any-file:

‎.github/workflows/release.yml‎

Lines changed: 27 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -36,55 +36,26 @@ env:
3636
CMAKE_ARGS: "-DLLAMA_BUILD_EXAMPLES=ON -DLLAMA_BUILD_TESTS=OFF -DLLAMA_BUILD_TOOLS=ON -DLLAMA_BUILD_SERVER=ON -DGGML_RPC=ON"
3737

3838
jobs:
39-
macOS-arm64:
40-
runs-on: macos-14
41-
42-
steps:
43-
- name: Clone
44-
id: checkout
45-
uses: actions/checkout@v6
46-
with:
47-
fetch-depth: 0
48-
49-
- name: ccache
50-
uses: ggml-org/ccache-action@v1.2.21
51-
with:
52-
key: macOS-latest-arm64
53-
evict-old-files: 1d
54-
55-
- name: Build
56-
id: cmake_build
57-
run: |
58-
sysctl -a
59-
cmake -B build \
60-
-DCMAKE_INSTALL_RPATH='@loader_path' \
61-
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
62-
-DLLAMA_FATAL_WARNINGS=ON \
63-
-DLLAMA_BUILD_BORINGSSL=ON \
64-
-DGGML_METAL_USE_BF16=ON \
65-
-DGGML_METAL_EMBED_LIBRARY=ON \
66-
-DGGML_RPC=ON \
67-
${{ env.CMAKE_ARGS }}
68-
cmake --build build --config Release -j $(sysctl -n hw.logicalcpu)
69-
70-
- name: Determine tag name
71-
id: tag
72-
uses: ./.github/actions/get-tag-name
73-
74-
- name: Pack artifacts
75-
id: pack_artifacts
76-
run: |
77-
cp LICENSE ./build/bin/
78-
tar -czvf llama-${{ steps.tag.outputs.name }}-bin-macos-arm64.tar.gz -s ",./,llama-${{ steps.tag.outputs.name }}/," -C ./build/bin .
79-
80-
- name: Upload artifacts
81-
uses: actions/upload-artifact@v6
82-
with:
83-
path: llama-${{ steps.tag.outputs.name }}-bin-macos-arm64.tar.gz
84-
name: llama-bin-macos-arm64.tar.gz
39+
macOS-cpu:
40+
strategy:
41+
matrix:
42+
include:
43+
- build: 'arm64'
44+
arch: 'arm64'
45+
os: macos-14
46+
defines: "-DGGML_METAL_USE_BF16=ON -DGGML_METAL_EMBED_LIBRARY=ON"
47+
- build: 'arm64-kleidiai'
48+
arch: 'arm64'
49+
os: macos-14
50+
defines: "-DGGML_METAL_USE_BF16=ON -DGGML_METAL_EMBED_LIBRARY=ON -DGGML_CPU_KLEIDIAI=ON"
51+
- build: 'x64'
52+
arch: 'x64'
53+
os: macos-15-intel
54+
# Metal is disabled on x64 due to intermittent failures with Github runners not having a GPU:
55+
# https://github.com/ggml-org/llama.cpp/actions/runs/8635935781/job/23674807267#step:5:2313
56+
defines: "-DGGML_METAL=OFF -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3"
8557

86-
macOS-x64:
87-
runs-on: macos-15-intel
58+
runs-on: ${{ matrix.os }}
8859

8960
steps:
9061
- name: Clone
@@ -96,23 +67,20 @@ jobs:
9667
- name: ccache
9768
uses: ggml-org/ccache-action@v1.2.21
9869
with:
99-
key: macOS-latest-x64
70+
key: macOS-latest-${{ matrix.arch }}
10071
evict-old-files: 1d
10172

10273
- name: Build
10374
id: cmake_build
10475
run: |
10576
sysctl -a
106-
# Metal is disabled due to intermittent failures with Github runners not having a GPU:
107-
# https://github.com/ggml-org/llama.cpp/actions/runs/8635935781/job/23674807267#step:5:2313
10877
cmake -B build \
78+
${{ matrix.defines }} \
10979
-DCMAKE_INSTALL_RPATH='@loader_path' \
11080
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
11181
-DLLAMA_FATAL_WARNINGS=ON \
11282
-DLLAMA_BUILD_BORINGSSL=ON \
113-
-DGGML_METAL=OFF \
114-
-DGGML_RPC=ON \
115-
-DCMAKE_OSX_DEPLOYMENT_TARGET=13.3
83+
${{ env.CMAKE_ARGS }}
11684
cmake --build build --config Release -j $(sysctl -n hw.logicalcpu)
11785
11886
- name: Determine tag name
@@ -123,13 +91,13 @@ jobs:
12391
id: pack_artifacts
12492
run: |
12593
cp LICENSE ./build/bin/
126-
tar -czvf llama-${{ steps.tag.outputs.name }}-bin-macos-x64.tar.gz -s ",./,llama-${{ steps.tag.outputs.name }}/," -C ./build/bin .
94+
tar -czvf llama-${{ steps.tag.outputs.name }}-bin-macos-${{ matrix.build }}.tar.gz -s ",./,llama-${{ steps.tag.outputs.name }}/," -C ./build/bin .
12795
12896
- name: Upload artifacts
12997
uses: actions/upload-artifact@v6
13098
with:
131-
path: llama-${{ steps.tag.outputs.name }}-bin-macos-x64.tar.gz
132-
name: llama-bin-macos-x64.tar.gz
99+
path: llama-${{ steps.tag.outputs.name }}-bin-macos-${{ matrix.build }}.tar.gz
100+
name: llama-bin-macos-${{ matrix.build }}.tar.gz
133101

134102
ubuntu-cpu:
135103
strategy:
@@ -1003,8 +971,7 @@ jobs:
1003971
- ubuntu-cpu
1004972
- ubuntu-vulkan
1005973
- ubuntu-24-openvino
1006-
- macOS-arm64
1007-
- macOS-x64
974+
- macOS-cpu
1008975
- ios-xcode-build
1009976
- openEuler-cann
1010977

@@ -1081,6 +1048,7 @@ jobs:
10811048
10821049
**macOS/iOS:**
10831050
- [macOS Apple Silicon (arm64)](https://github.com/Thireus/llama.cpp/releases/download/${{ steps.tag.outputs.name }}/llama-${{ steps.tag.outputs.name }}-bin-macos-arm64.tar.gz)
1051+
- [macOS Apple Silicon (arm64, KleidiAI enabled)](https://github.com/Thireus/llama.cpp/releases/download/${{ steps.tag.outputs.name }}/llama-${{ steps.tag.outputs.name }}-bin-macos-arm64-kleidiai.tar.gz)
10841052
- [macOS Intel (x64)](https://github.com/Thireus/llama.cpp/releases/download/${{ steps.tag.outputs.name }}/llama-${{ steps.tag.outputs.name }}-bin-macos-x64.tar.gz)
10851053
- [iOS XCFramework](https://github.com/Thireus/llama.cpp/releases/download/${{ steps.tag.outputs.name }}/llama-${{ steps.tag.outputs.name }}-xcframework.zip)
10861054

‎common/chat-auto-parser-generator.cpp‎

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -332,58 +332,36 @@ common_peg_parser analyze_tools::build_tool_parser_tag_tagged(parser_build_conte
332332
const auto & inputs = ctx.inputs;
333333
bool force_tools = inputs.tool_choice == COMMON_CHAT_TOOL_CHOICE_REQUIRED;
334334

335+
auto until_suffix = p.rule("until-suffix", p.until(arguments.value_suffix));
336+
335337
common_peg_parser tool_choice = p.choice();
336338

337339
foreach_function(inputs.tools, [&](const json & tool) {
338340
const auto & func = tool.at("function");
339341
std::string name = func.at("name");
340-
const auto & params = func.contains("parameters") ? func.at("parameters") : json::object();
342+
auto params = func.contains("parameters") ? func.at("parameters") : json::object();
341343
const auto & properties = params.contains("properties") ? params.at("properties") : json::object();
344+
342345
std::set<std::string> required;
346+
if (params.contains("required")) {
347+
params.at("required").get_to(required);
348+
}
349+
350+
auto schema_info = common_schema_info();
351+
schema_info.resolve_refs(params);
343352

344353
// Build parser for each argument, separating required and optional
345354
std::vector<common_peg_parser> required_parsers;
346355
std::vector<common_peg_parser> optional_parsers;
347356
for (const auto & [param_name, param_schema] : properties.items()) {
348-
bool is_required = required.find(param_name) != required.end();
349-
std::string type = "object";
350-
if (param_schema.contains("type")) {
351-
const auto & type_obj = param_schema.at("type");
352-
if (type_obj.is_string()) {
353-
type_obj.get_to(type);
354-
} else if (type_obj.is_array()) {
355-
// Handle nullable types like ["string", "null"]
356-
for (const auto & t : type_obj) {
357-
if (t.is_string() && t.get<std::string>() != "null") {
358-
type = t.get<std::string>();
359-
break;
360-
}
361-
}
362-
} else if (type_obj.is_object()) {
363-
if (type_obj.contains("type") && type_obj.at("type").is_string()) {
364-
type_obj.at("type").get_to(type);
365-
}
366-
}
367-
}
368-
// Infer string type from enum values when type is unspecified
369-
if (type == "object" && param_schema.contains("enum")) {
370-
const auto & enum_vals = param_schema.at("enum");
371-
if (enum_vals.is_array()) {
372-
for (const auto & v : enum_vals) {
373-
if (v.is_string()) {
374-
type = "string";
375-
break;
376-
}
377-
}
378-
}
379-
}
357+
bool is_required = required.find(param_name) != required.end();
380358

381359
auto arg =
382360
p.tool_arg(p.tool_arg_open(arguments.name_prefix + p.tool_arg_name(p.literal(param_name)) +
383361
arguments.name_suffix) +
384362
arguments.value_prefix +
385-
(type == "string" ?
386-
p.tool_arg_string_value(p.schema(p.until(arguments.value_suffix),
363+
(schema_info.resolves_to_string(param_schema) ?
364+
p.tool_arg_string_value(p.schema(until_suffix,
387365
"tool-" + name + "-arg-" + param_name + "-schema",
388366
param_schema, true)) :
389367
p.tool_arg_json_value(p.schema(
@@ -414,7 +392,7 @@ common_peg_parser analyze_tools::build_tool_parser_tag_tagged(parser_build_conte
414392
for (const auto & opt : optional_parsers) {
415393
any_opt |= opt;
416394
}
417-
args_seq = args_seq + p.repeat(p.space() + any_opt, 0, (int) optional_parsers.size());
395+
args_seq = args_seq + p.repeat(p.space() + any_opt, 0, -1);
418396
}
419397

420398
if (!arguments.start.empty()) {

‎common/chat.cpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,7 +1124,7 @@ static common_chat_params common_chat_params_init_gemma4(const common_chat_templ
11241124
p.rule("gemma4-bool", p.json_bool());
11251125
p.rule("gemma4-null", p.json_null());
11261126
p.rule("gemma4-number", p.json_number());
1127-
p.rule("gemma4-dict-key", p.rule("gemma4-dict-key-name", p.until(":")) + p.literal(":"));
1127+
p.rule("gemma4-dict-key", p.rule("gemma4-dict-key-name", p.chars("[^:}]", 1, -1)) + p.literal(":"));
11281128
p.rule("gemma4-dict-kv", p.ref("gemma4-dict-key") + p.space() + p.ref("gemma4-value"));
11291129
p.rule("gemma4-dict", [&]() {
11301130
auto ws = p.space();
@@ -1963,7 +1963,7 @@ static common_chat_params common_chat_templates_apply_jinja(const struct common_
19631963
params.add_generation_prompt = true;
19641964
std::string gen_prompt = common_chat_template_direct_apply_impl(tmpl, params);
19651965
auto diff = calculate_diff_split(no_gen_prompt, gen_prompt);
1966-
params.generation_prompt = diff.right;
1966+
params.generation_prompt = diff.right + diff.suffix;
19671967

19681968
params.add_generation_prompt = inputs.add_generation_prompt;
19691969

‎common/download.cpp‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,10 @@ static hf_cache::hf_file find_best_model(const hf_cache::hf_files & files,
591591
for (const auto & f : files) {
592592
if (gguf_filename_is_model(f.path) &&
593593
std::regex_search(f.path, pattern)) {
594+
auto split = get_gguf_split_info(f.path);
595+
if (split.count > 1 && split.index != 1) {
596+
continue;
597+
}
594598
return f;
595599
}
596600
}
@@ -600,6 +604,10 @@ static hf_cache::hf_file find_best_model(const hf_cache::hf_files & files,
600604
if (tag.empty()) {
601605
for (const auto & f : files) {
602606
if (gguf_filename_is_model(f.path)) {
607+
auto split = get_gguf_split_info(f.path);
608+
if (split.count > 1 && split.index != 1) {
609+
continue;
610+
}
603611
return f;
604612
}
605613
}
@@ -618,6 +626,7 @@ static void list_available_gguf_files(const hf_cache::hf_files & files) {
618626
}
619627

620628
struct hf_plan {
629+
hf_cache::hf_file primary;
621630
hf_cache::hf_files model_files;
622631
hf_cache::hf_file mmproj;
623632
};
@@ -663,6 +672,7 @@ static hf_plan get_hf_plan(const common_params_model & model,
663672
}
664673
}
665674

675+
plan.primary = primary;
666676
plan.model_files = get_split_files(all, primary);
667677

668678
if (opts.download_mmproj) {
@@ -749,7 +759,7 @@ common_download_model_result common_download_model(const common_params_model
749759
for (const auto & f : hf.model_files) {
750760
hf_cache::finalize_file(f);
751761
}
752-
result.model_path = hf.model_files[0].final_path;
762+
result.model_path = hf.primary.final_path;
753763

754764
if (!hf.mmproj.path.empty()) {
755765
result.mmproj_path = hf_cache::finalize_file(hf.mmproj);

‎common/jinja/runtime.cpp‎

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,23 @@ value binary_expression::execute_impl(context & ctx) {
251251
return res;
252252
}
253253

254+
// Python-style string repetition
255+
// TODO: support array/tuple repetition (e.g., [1, 2] * 3 → [1, 2, 1, 2, 1, 2])
256+
if (op.value == "*" &&
257+
((is_val<value_string>(left_val) && is_val<value_int>(right_val)) ||
258+
(is_val<value_int>(left_val) && is_val<value_string>(right_val)))) {
259+
const auto & str = is_val<value_string>(left_val) ? left_val->as_string() : right_val->as_string();
260+
const int64_t repeat = is_val<value_int>(right_val) ? right_val->as_int() : left_val->as_int();
261+
auto res = mk_val<value_string>();
262+
if (repeat <= 0) {
263+
return res;
264+
}
265+
for (int64_t i = 0; i < repeat; ++i) {
266+
res->val_str = res->val_str.append(str);
267+
}
268+
return res;
269+
}
270+
254271
// String membership
255272
if (is_val<value_string>(left_val) && is_val<value_string>(right_val)) {
256273
// case: "a" in "abc"

0 commit comments

Comments
 (0)