Skip to content

Commit 3b0dd4e

Browse files
committed
Split toolcall into separate library
1 parent 4d81086 commit 3b0dd4e

17 files changed

+101
-49
lines changed

CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ option(LLAMA_BUILD_SERVER "llama: build server example" ${LLAMA_STANDALONE})
8282
option(LLAMA_CURL "llama: use libcurl to download model from an URL" OFF)
8383
option(LLAMA_LLGUIDANCE "llama-common: include LLGuidance library for structured output in common utils" OFF)
8484

85+
# Toolcall support - needs LLAMA_CURL support to connect with SSE endpoints
86+
option(LLAMA_TOOLCALL "llama: add toolcall support via Model Context Protocol" OFF)
87+
8588
# Required for relocatable CMake package
8689
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/build-info.cmake)
8790
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/common.cmake)
@@ -160,6 +163,10 @@ add_subdirectory(src)
160163
# utils, programs, examples and tests
161164
#
162165

166+
if (LLAMA_TOOLCALL)
167+
add_subdirectory(toolcall)
168+
endif()
169+
163170
if (LLAMA_BUILD_COMMON)
164171
add_subdirectory(common)
165172
endif()

common/CMakeLists.txt

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,6 @@ add_library(${TARGET} STATIC
7575
sampling.h
7676
speculative.cpp
7777
speculative.h
78-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/params.cpp
79-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/params.h
80-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/handler.cpp
81-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/handler.h
82-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/mcp_messages.cpp
83-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/mcp_messages.h
84-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/mcp_transport.h
85-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/mcp_stdio_transport.cpp
86-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/mcp_stdio_transport.h
8778
)
8879

8980
if (BUILD_SHARED_LIBS)
@@ -99,11 +90,6 @@ if (LLAMA_CURL)
9990
include_directories(${CURL_INCLUDE_DIRS})
10091
find_library(CURL_LIBRARY curl REQUIRED)
10192
set(LLAMA_COMMON_EXTRA_LIBS ${LLAMA_COMMON_EXTRA_LIBS} ${CURL_LIBRARY})
102-
103-
target_sources(${TARGET}
104-
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/toolcall/mcp_sse_transport.cpp
105-
${CMAKE_CURRENT_SOURCE_DIR}/toolcall/mcp_sse_transport.h)
106-
10793
endif ()
10894

10995
if (LLAMA_LLGUIDANCE)
@@ -153,3 +139,7 @@ endif ()
153139
target_include_directories(${TARGET} PUBLIC .)
154140
target_compile_features (${TARGET} PUBLIC cxx_std_17)
155141
target_link_libraries (${TARGET} PRIVATE ${LLAMA_COMMON_EXTRA_LIBS} PUBLIC llama Threads::Threads)
142+
143+
if (LLAMA_TOOLCALL)
144+
target_link_libraries(${TARGET} PUBLIC toolcall)
145+
endif()

common/arg.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2143,21 +2143,24 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
21432143
}
21442144
).set_examples({LLAMA_EXAMPLE_MAIN, LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_CHAT_TEMPLATE_FILE"));
21452145

2146+
#ifdef LLAMA_USE_TOOLCALL
21462147
add_opt(common_arg(
21472148
{"--tools"}, "JINJA_TOOLS",
2148-
"set to JSON array of tool definitions used for assistant function-calling (requires --jinja)",
2149+
"set to URI of a Model Context Protocol server, or "
2150+
"a JSON array containing tool definitions (requires --jinja)",
21492151
[](common_params &params, const std::string & value) {
21502152
params.jinja_tools.tools(value);
21512153

21522154
}).set_examples({LLAMA_EXAMPLE_MAIN}));
21532155

21542156
add_opt(common_arg(
21552157
{"--tool-choice"}, "JINJA_TOOL_CHOICE",
2156-
"set to \"auto\", \"required\", \"none\" or a JSON object specifying a tool function (default: \"auto\")",
2158+
"set to \"auto\", \"required\", or \"none\" (default: \"auto\")",
21572159
[](common_params &params, const std::string & value) {
21582160
params.jinja_tools.choice(value);
21592161

21602162
}).set_examples({LLAMA_EXAMPLE_MAIN}));
2163+
#endif
21612164

21622165
add_opt(common_arg(
21632166
{"-sps", "--slot-prompt-similarity"}, "SIMILARITY",

common/common.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
#pragma once
44

55
#include "llama-cpp.h"
6-
#include "toolcall/params.h"
6+
7+
#ifdef LLAMA_USE_TOOLCALL
8+
# include "toolcall-params.h"
9+
#endif
10+
711
#include <set>
812
#include <string>
913
#include <vector>
@@ -353,7 +357,11 @@ struct common_params {
353357
std::string chat_template = ""; // NOLINT
354358
bool use_jinja = false; // NOLINT
355359
bool enable_chat_template = true;
360+
361+
#ifdef LLAMA_USE_TOOLCALL
356362
toolcall::params jinja_tools;
363+
#endif
364+
357365
common_reasoning_format reasoning_format = COMMON_REASONING_FORMAT_DEEPSEEK;
358366

359367
std::vector<std::string> api_keys;

examples/main/main.cpp

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include "sampling.h"
66
#include "llama.h"
77
#include "chat.h"
8-
#include "toolcall/handler.h"
98

109
#include <cstdio>
1110
#include <cstring>
@@ -16,6 +15,10 @@
1615
#include <string>
1716
#include <vector>
1817

18+
#ifdef LLAMA_USE_TOOLCALL
19+
# include "toolcall-handler.h"
20+
#endif
21+
1922
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
2023
#include <signal.h>
2124
#include <unistd.h>
@@ -264,11 +267,14 @@ int main(int argc, char ** argv) {
264267

265268
std::vector<llama_token> embd_inp;
266269

267-
auto toolcall_handler = toolcall::create_handler(params.jinja_tools);
270+
#ifdef LLAMA_USE_TOOLCALL
271+
auto tc_handler = toolcall::create_handler(params.jinja_tools);
272+
#else
273+
void * tc_handler = nullptr; // placeholder
274+
#endif
268275

269-
auto chat_add_and_format = [&chat_msgs, &chat_templates, &sparams, vocab](
270-
const std::string & role, const std::string & content,
271-
toolcall::handler::ptr handler = nullptr)
276+
auto chat_add_and_format = [&chat_msgs, &chat_templates, &sparams, vocab, tc_handler](
277+
const std::string & role, const std::string & content, bool use_toolcalls = false)
272278
{
273279
bool add_ass = (role == "user");
274280

@@ -277,11 +283,13 @@ int main(int argc, char ** argv) {
277283
new_msg.content = content;
278284

279285
common_chat_templates_inputs cinputs;
280-
if (handler != nullptr) {
281-
cinputs.tool_choice = common_chat_tool_choice_parse_oaicompat(handler->tool_choice());
282-
cinputs.tools = common_chat_tools_parse_oaicompat(handler->tool_list());
283-
}
284286

287+
#ifdef LLAMA_USE_TOOLCALL
288+
if (tc_handler != nullptr && use_toolcalls) {
289+
cinputs.tool_choice = common_chat_tool_choice_parse_oaicompat(tc_handler->tool_choice());
290+
cinputs.tools = common_chat_tools_parse_oaicompat(tc_handler->tool_list());
291+
}
292+
#endif
285293
common_chat_params cparams;
286294
auto formatted =
287295
common_chat_format_single(chat_templates.get(), chat_msgs, new_msg, add_ass, g_params->use_jinja,
@@ -290,23 +298,24 @@ int main(int argc, char ** argv) {
290298
chat_msgs.push_back(new_msg);
291299
LOG_DBG("formatted: '%s'\n", formatted.c_str());
292300

301+
#ifdef LLAMA_USE_TOOLCALL
293302
if (g_params->use_jinja) {
294303
common_chat_grammar_to_sampler(&cparams, vocab, &sparams);
295-
if (handler != nullptr) {
304+
if (tc_handler != nullptr) {
296305
std::string response;
297-
handler->call(formatted, response);
306+
tc_handler->call(formatted, response);
298307
return std::string(response);
299308
}
300309
}
310+
#endif
301311
return formatted;
302312
};
303313

304314
{
305-
std::string system_prompt (params.prompt.empty() ? DEFAULT_SYSTEM_MESSAGE : params.prompt);
306-
bool use_conversation_prompt (params.conversation_mode && params.enable_chat_template);
315+
std::string system_prompt = params.prompt.empty() ? DEFAULT_SYSTEM_MESSAGE : params.prompt;
316+
bool use_conversation_prompt = params.conversation_mode && params.enable_chat_template;
307317
auto prompt = use_conversation_prompt ?
308-
chat_add_and_format("system", system_prompt, toolcall_handler)
309-
: params.prompt;
318+
chat_add_and_format("system", system_prompt, true) : params.prompt;
310319

311320
if (params.interactive_first || !params.prompt.empty() || session_tokens.empty()) {
312321
LOG_DBG("tokenize the prompt\n");
@@ -814,23 +823,22 @@ int main(int argc, char ** argv) {
814823
}
815824

816825
if (params.enable_chat_template) {
817-
auto output = chat_add_and_format("assistant", assistant_ss.str(), toolcall_handler);
818-
if (toolcall_handler != nullptr) {
819-
auto action = toolcall_handler->last_action();
820-
if (action == toolcall::ACCEPT) {
821-
LOG_DBG("tokenizing toolcall response");
822-
auto response = common_tokenize(ctx, output, false, true);
823-
embd_inp.insert(embd_inp.end(), response.begin(), response.end());
824-
825-
} else {
826-
is_interacting = true;
827-
LOG("\n");
828-
}
829-
830-
} else {
826+
#ifdef LLAMA_USE_TOOLCALL
827+
auto output = chat_add_and_format("assistant", assistant_ss.str(), true);
828+
if (tc_handler == nullptr || tc_handler->last_action() != toolcall::ACCEPT) {
831829
is_interacting = true;
832830
LOG("\n");
831+
832+
} else {
833+
LOG_DBG("tokenizing toolcall response");
834+
auto response = common_tokenize(ctx, output, false, true);
835+
embd_inp.insert(embd_inp.end(), response.begin(), response.end());
833836
}
837+
#else
838+
chat_add_and_format("assistant", assistant_ss.str());
839+
is_interacting = true;
840+
LOG("\n");
841+
#endif
834842
}
835843
}
836844
}

toolcall/CMakeLists.txt

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
set(TARGET toolcall)
3+
4+
set(SOURCES
5+
handler.cpp
6+
mcp_messages.cpp
7+
mcp_stdio_transport.cpp
8+
params.cpp
9+
)
10+
11+
set(HEADERS
12+
toolcall-params.h
13+
toolcall-handler.h
14+
mcp_transport.h
15+
mcp_messages.h
16+
mcp_stdio_transport.h
17+
)
18+
19+
add_library(${TARGET} STATIC ${SOURCES} ${HEADERS})
20+
21+
target_include_directories(${TARGET} # Right now only for "json.hpp"
22+
PRIVATE $<TARGET_PROPERTY:common,INTERFACE_INCLUDE_DIRECTORIES>)
23+
24+
if (LLAMA_CURL)
25+
find_package(CURL REQUIRED)
26+
target_compile_definitions(${TARGET} PUBLIC LLAMA_USE_CURL)
27+
include_directories(${CURL_INCLUDE_DIRS})
28+
find_library(CURL_LIBRARY curl REQUIRED)
29+
30+
target_link_libraries(${TARGET} PRIVATE ${CURL_LIBRARY})
31+
target_sources(${TARGET} PRIVATE mcp_sse_transport.cpp mcp_sse_transport.h)
32+
33+
endif()
34+
35+
target_compile_definitions(${TARGET} INTERFACE LLAMA_USE_TOOLCALL)
36+
target_include_directories(${TARGET} PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>)

common/toolcall/handler.cpp renamed to toolcall/handler.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
#include <json.hpp>
3-
#include "handler.h"
3+
#include "toolcall-handler.h"
44

55
#ifdef LLAMA_USE_CURL
66
# include "mcp_sse_transport.h"
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)