mirror of
https://github.com/wolfpld/tracy.git
synced 2026-10-13 12:25:22 +00:00
Perform tool calls with json.
This commit is contained in:
@@ -26,16 +26,13 @@ The user is asking about the weather in San Francisco. I need to use the weather
|
||||
2. *Tool Usage (`<tool>`):*
|
||||
- If, in the `<think>` block, you decide you need to use a tool, the next block generated *MUST* be a `<tool>` block.
|
||||
- The tag name MUST be exactly `tool`.
|
||||
- The first line inside the `<tool>` block *MUST* contain the *exact function name* from the list of available tools.
|
||||
- If the function requires parameters, provide them on subsequent lines, *one parameter per line*. Provide parameters in plain form, *without quotation marks*.
|
||||
- *After generating a `<tool>` block, you MUST END YOUR RESPONSE FOR THIS TURN.* Do not generate any other text or tags after the `<tool>` block. The system will process this tool call and provide you with the result in the next step.
|
||||
- Example:
|
||||
- The tool name and its parameters (if applicable) must be passed as a json data. For example:
|
||||
<think>
|
||||
The user is asking about the weather in San Francisco. I need to use the weather checking tool. The function name is 'check_weather', the parameter is the city name.
|
||||
The user is asking about the weather in San Francisco. I need to use the weather checking tool. The tool name is 'check_weather', the parameter is the city name.
|
||||
</think>
|
||||
<tool>
|
||||
check_weather
|
||||
San Francisco
|
||||
{"tool": "check_weather", "city": "San Francisco"}
|
||||
</tool>
|
||||
|
||||
3. *Tool Output (`<tool_output>`):*
|
||||
|
||||
@@ -733,20 +733,6 @@ void TracyLlm::SendMessage( std::unique_lock<std::mutex>& lock )
|
||||
}
|
||||
}
|
||||
|
||||
static std::vector<std::string> SplitLines( const std::string& str )
|
||||
{
|
||||
std::vector<std::string> lines;
|
||||
auto pos = 0;
|
||||
while( pos < str.size() )
|
||||
{
|
||||
auto next = str.find( '\n', pos );
|
||||
if( next == std::string::npos ) next = str.size();
|
||||
if( pos != next ) lines.emplace_back( str.substr( pos, next - pos ) );
|
||||
pos = next + 1;
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
bool TracyLlm::OnResponse( const nlohmann::json& json )
|
||||
{
|
||||
std::unique_lock lock( m_lock );
|
||||
@@ -804,24 +790,29 @@ bool TracyLlm::OnResponse( const nlohmann::json& json )
|
||||
if( end != std::string::npos )
|
||||
{
|
||||
while( end > pos && str[end-1] == '\n' ) end--;
|
||||
auto data = str.substr( pos, end - pos );
|
||||
auto lines = SplitLines( data );
|
||||
if( !lines.empty() )
|
||||
const auto tool = str.substr( pos, end - pos );
|
||||
lock.unlock();
|
||||
|
||||
TracyLlmTools::ToolReply reply;
|
||||
try
|
||||
{
|
||||
isTool = true;
|
||||
auto tool = lines[0];
|
||||
lines.erase( lines.begin() );
|
||||
lock.unlock();
|
||||
const auto reply = m_tools->HandleToolCalls( tool, lines, *m_api, m_api->GetModels()[m_modelIdx].contextSize, m_embedIdx >= 0 );
|
||||
auto output = "<tool_output>\n" + reply.reply;
|
||||
lock.lock();
|
||||
AddMessage( std::move( output ), "user" );
|
||||
m_jobs.emplace_back( WorkItem {
|
||||
.task = Task::SendMessage,
|
||||
.callback = nullptr
|
||||
} );
|
||||
m_cv.notify_all();
|
||||
auto json = nlohmann::json::parse( tool );
|
||||
reply = m_tools->HandleToolCalls( json, *m_api, m_api->GetModels()[m_modelIdx].contextSize, m_embedIdx >= 0 );
|
||||
}
|
||||
catch( const nlohmann::json::exception& e )
|
||||
{
|
||||
reply.reply = e.what();
|
||||
}
|
||||
|
||||
isTool = true;
|
||||
auto output = "<tool_output>\n" + reply.reply;
|
||||
lock.lock();
|
||||
AddMessage( std::move( output ), "user" );
|
||||
m_jobs.emplace_back( WorkItem {
|
||||
.task = Task::SendMessage,
|
||||
.callback = nullptr
|
||||
} );
|
||||
m_cv.notify_all();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,51 +181,49 @@ TracyLlmTools::~TracyLlmTools()
|
||||
CancelManualEmbeddings();
|
||||
}
|
||||
|
||||
TracyLlmTools::ToolReply TracyLlmTools::HandleToolCalls( const std::string& name, const std::vector<std::string>& args, TracyLlmApi& api, int contextSize, bool hasEmbeddingsModel )
|
||||
#define Param(name) json[name].get_ref<const std::string&>()
|
||||
|
||||
TracyLlmTools::ToolReply TracyLlmTools::HandleToolCalls( const nlohmann::json& json, TracyLlmApi& api, int contextSize, bool hasEmbeddingsModel )
|
||||
{
|
||||
m_ctxSize = contextSize;
|
||||
|
||||
if( name == "fetch_web_page" )
|
||||
try
|
||||
{
|
||||
if( args.empty() ) return { .reply = "Missing URL argument" };
|
||||
return { .reply = FetchWebPage( args[0] ) };
|
||||
auto name = json["tool"].get_ref<const std::string&>();
|
||||
if( name == "search_wikipedia" )
|
||||
{
|
||||
return SearchWikipedia( Param( "query" ), Param( "language" ) );
|
||||
}
|
||||
else if( name == "get_wikipedia" )
|
||||
{
|
||||
return { .reply = GetWikipedia( Param( "page" ), Param( "language" ) ) };
|
||||
}
|
||||
else if( name == "get_dictionary" )
|
||||
{
|
||||
return { .reply = GetDictionary( Param( "word" ), Param( "language" ) ) };
|
||||
}
|
||||
else if( name == "search_web" )
|
||||
{
|
||||
return { .reply = SearchWeb( Param( "query" ) ) };
|
||||
}
|
||||
else if( name == "get_webpage" )
|
||||
{
|
||||
return { .reply = GetWebpage( Param( "url" ) ) };
|
||||
}
|
||||
else if( name == "user_manual" )
|
||||
{
|
||||
return { .reply = SearchManual( Param( "query" ), api, hasEmbeddingsModel ) };
|
||||
}
|
||||
return { .reply = "Unknown tool call: " + name };
|
||||
}
|
||||
if( name == "search_wikipedia" )
|
||||
catch( const nlohmann::json::exception& e )
|
||||
{
|
||||
if( args.empty() ) return { .reply = "Missing search term argument" };
|
||||
if( args.size() < 2 ) return { .reply = "Missing language argument" };
|
||||
return SearchWikipedia( args[0], args[1] );
|
||||
return { .reply = e.what() };
|
||||
}
|
||||
if( name == "get_wikipedia" )
|
||||
{
|
||||
if( args.empty() ) return { .reply = "Missing page name argument" };
|
||||
if( args.size() < 2 ) return { .reply = "Missing language argument" };
|
||||
return { .reply = GetWikipedia( args[0], args[1] ) };
|
||||
}
|
||||
if( name == "get_dictionary" )
|
||||
{
|
||||
if( args.empty() ) return { .reply = "Missing word argument" };
|
||||
if( args.size() < 2 ) return { .reply = "Missing language argument" };
|
||||
return { .reply = GetDictionary( args[0], args[1] ) };
|
||||
}
|
||||
if( name == "search_web" )
|
||||
{
|
||||
if( args.empty() ) return { .reply = "Missing search term argument" };
|
||||
return { .reply = SearchWeb( args[0] ) };
|
||||
}
|
||||
if( name == "get_webpage" )
|
||||
{
|
||||
if( args.empty() ) return { .reply = "Missing URL argument" };
|
||||
return { .reply = GetWebpage( args[0] ) };
|
||||
}
|
||||
if( name == "user_manual" )
|
||||
{
|
||||
if( args.empty() ) return { .reply = "Missing search term argument" };
|
||||
return { .reply = SearchManual( args[0], api, hasEmbeddingsModel ) };
|
||||
}
|
||||
return { .reply = "Unknown tool call: " + name };
|
||||
}
|
||||
|
||||
#undef Param
|
||||
|
||||
std::string TracyLlmTools::GetCurrentTime() const
|
||||
{
|
||||
auto t = time( nullptr );
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#ifndef __TRACYLLMTOOLS_HPP__
|
||||
#define __TRACYLLMTOOLS_HPP__
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
@@ -37,7 +38,7 @@ public:
|
||||
TracyLlmTools();
|
||||
~TracyLlmTools();
|
||||
|
||||
ToolReply HandleToolCalls( const std::string& name, const std::vector<std::string>& args, TracyLlmApi& api, int contextSize, bool hasEmbeddingsModel );
|
||||
ToolReply HandleToolCalls( const nlohmann::json& json, TracyLlmApi& api, int contextSize, bool hasEmbeddingsModel );
|
||||
std::string GetCurrentTime() const;
|
||||
|
||||
[[nodiscard]] EmbeddingState GetManualEmbeddingsState() const;
|
||||
|
||||
Reference in New Issue
Block a user