Compare commits

...

12 Commits

Author SHA1 Message Date
HanishKVC 28ddd2c474 ChatON: ChatParts dump returns info str rather than direct logging 2024-05-14 02:21:16 +05:30
HanishKVC 4dfd10a40d ChatON: Move core templating/tagging code into ChatTemplates class
However still retain the wrappers, which work with a predefined
global instance of ChatTemplates.
2024-05-14 01:49:38 +05:30
HanishKVC 600653dae2 ChatON:Optional control of MsgCntBasedTagging
Use same to bypass any msg count based tagging behaviour for the
single message tagging through its helper wrapper.
2024-05-14 01:27:24 +05:30
HanishKVC 6e13c0c87e ChatON:Control SystemMsgSuffix+End tags only wrt 1st system msg
Make it similar to user-begin+prefix control. ie only wrt 1st msg
of respective type.
2024-05-14 01:19:04 +05:30
HanishKVC 3fcaf19967 ChatON+:Multi4Single: applyGlobalIfAny flag wrt templating api
Given that now the multi chat templating logic itself is used to
apply chat templating/tagging to a single chat message, so give
flexibility of deciding whether global tags if any should be
applied or not wrt the core tagging logic.

examples/main inturn updated to not apply global tags if any wrt
the system message. Also the user messages already dont apply
global tags if any, as its currently implemented to build on the
existing in-prefix/suffix and anitprompt flow.
2024-05-14 01:00:17 +05:30
HanishKVC 8165bd4035 ChatON:WIP:chaton_tmpl_apply_single build on multi msg tagging
To avoid having to duplicate any hardcoding in future, wrt any new
model/chat-template-standard, at multiple locations, remove the
single message templating code with a wrapper which does the same
but using the multi-msg templating helper.
2024-05-14 00:44:47 +05:30
HanishKVC fe0c9ce646 ChatON:BasicCheck+:return a string with info, dont directly log 2024-05-14 00:25:00 +05:30
HanishKVC efbb87dba6 ChatON:ChatTemplates:TmplBasicCheck 2024-05-13 17:50:15 +05:30
HanishKVC 0cfe99076d ChatON:ChatTemplates: TmplExists, TmplGetKey, TmplRoleGetKeys
ChatTemplate directly supports these now, as well as the existing
global instance based corresponding helpers depend on same.
2024-05-13 17:30:47 +05:30
HanishKVC 184ac322e3 ChatON: Make json_get efficient and flexible wrt its calling
Also explicitly indicate that we are looking at a chain of keys
2024-05-13 16:21:02 +05:30
HanishKVC eb7554ca3b ChatON: Avoid -> to match simpcfg as well as corresponding keys 2024-05-13 10:37:14 +05:30
HanishKVC d5b0bfbaec SimpCfg: Remove now unused SC_DEBUG, rather GroupKV uses equiv
The code which was using SC_DEBUG moved to GroupKV and inturn
GKV_DEBUG
2024-05-13 00:33:36 +05:30
3 changed files with 283 additions and 259 deletions

View File

@ -94,7 +94,7 @@
*
* The fields that make up a given chat-handshake-template-standard include
*
* * global-> begin & end
* * global -> begin & end
*
* * system -> begin, prefix, suffix & end
*
@ -281,19 +281,21 @@ public:
return typeid(*this).name();
}
void dump() {
std::string dump(const std::string &msgTag) {
std::stringstream ss;
std::string me = name() + ":" + __func__;
LOGXLN("INFO:%s:NumTypes:%zu", me.c_str(), types.length());
LOGXLN("INFO:%s:NumParts:%zu", me.c_str(), parts.size());
LOGXLN("INFO:%s:StrLength:%zu", me.c_str(), str().length());
ss << msgTag << ":NumTypes:" << types.length() << std::endl;
ss << msgTag << ":NumParts:" << parts.size() << std::endl;
ss << msgTag << ":StrLength:" << str().length() << std::endl;
if (parts.size() != types.length()) {
LOG_TEELN("DBUG:%s:Mismatch between parts and types", me.c_str());
LOG_TEELN("DBUG:%s:Mismatch between parts[%zu] and types[%zu]", me.c_str(), parts.size(), types.length());
}
int i = 0;
for(auto part: parts) {
LOGXLN("INFO:%s:%c:%s", me.c_str(), types[i], part.c_str());
ss << msgTag << ":Part:" << i << ":" << types[i] << ":" << part << std::endl;
i += 1;
}
return ss.str();
}
};
@ -305,6 +307,213 @@ public:
ChatTemplates(GroupKVMapMapVariant defaultMap) : GroupKV(defaultMap) {}
/**
* Check if the specified chat-template exists or not.
* NOTE: This doesnt cross check, if the template inturn contains all the required fields or not.
*/
bool tmpl_exists(const std::string &tmpl) {
if (!group_exists(tmpl)) {
LOG_TEELN("WARN:CT:%s: tmpl[%s] not found...", __func__, tmpl.c_str());
return false;
}
return true;
}
/**
* Check if all expected keys/fields are present wrt the specified chat-template.
* If any key/field is missing, expect a exception.
*
* Additionally also return a string containing info about all the fields.
*/
bool tmpl_basiccheck(const std::string &tmpl, std::stringstream &ss, const std::string &msgTag) {
if (!tmpl_exists(tmpl)) {
LOGXLN("ERRR:CT:%s:Specified template-id [%s] not found", msgTag.c_str(), tmpl.c_str());
return false;
}
std::string globalBegin = get_value<std::string>(tmpl, { K_GLOBAL, K_BEGIN });
std::string globalEnd = get_value<std::string>(tmpl, { K_GLOBAL, K_END });
std::string systemBegin = get_value<std::string>(tmpl, { K_SYSTEM, K_BEGIN });
std::string systemPrefix = get_value<std::string>(tmpl, { K_SYSTEM, K_PREFIX });
std::string systemSuffix = get_value<std::string>(tmpl, { K_SYSTEM, K_SUFFIX });
std::string systemEnd = get_value<std::string>(tmpl, { K_SYSTEM, K_END });
std::string userBegin = get_value<std::string>(tmpl, { K_USER, K_BEGIN });
std::string userPrefix = get_value<std::string>(tmpl, { K_USER, K_PREFIX });
std::string userSuffix = get_value<std::string>(tmpl, { K_USER, K_SUFFIX });
std::string userEnd = get_value<std::string>(tmpl, { K_USER, K_END });
std::string assistantBegin = get_value<std::string>(tmpl, { K_ASSISTANT, K_BEGIN });
std::string assistantPrefix = get_value<std::string>(tmpl, { K_ASSISTANT, K_PREFIX });
std::string assistantSuffix = get_value<std::string>(tmpl, { K_ASSISTANT, K_SUFFIX });
std::string assistantEnd = get_value<std::string>(tmpl, { K_ASSISTANT, K_END });
std::string reversePrompt = get_value<std::string>(tmpl, { K_REVERSE_PROMPT });
bool systemHasSuffix = get_value<bool>(tmpl, { K_SYSTEMUSER_SYSTEM_HAS_SUFFIX });
bool systemHasEnd = get_value<bool>(tmpl, { K_SYSTEMUSER_SYSTEM_HAS_END });
bool userHasBegin = get_value<bool>(tmpl, { K_SYSTEMUSER_1ST_USER_HAS_BEGIN });
bool userHasPrefix = get_value<bool>(tmpl, { K_SYSTEMUSER_1ST_USER_HAS_PREFIX });
ss << msgTag << ":" + tmpl + ":" << "global-begin" << ":" << globalBegin << std::endl;
ss << msgTag << ":" + tmpl + ":" << "global-end" << ":" << globalEnd << std::endl;
ss << msgTag << ":" + tmpl + ":" << "system-begin" << ":" << systemBegin << std::endl;
ss << msgTag << ":" + tmpl + ":" << "system-prefix" << ":" << systemPrefix << std::endl;
ss << msgTag << ":" + tmpl + ":" << "system-suffix" << ":" << systemSuffix << std::endl;
ss << msgTag << ":" + tmpl + ":" << "system-end" << ":" << systemEnd << std::endl;
ss << msgTag << ":" + tmpl + ":" << "user-begin" << ":" << userBegin << std::endl;
ss << msgTag << ":" + tmpl + ":" << "user-prefix" << ":" << userPrefix << std::endl;
ss << msgTag << ":" + tmpl + ":" << "user-suffix" << ":" << userSuffix << std::endl;
ss << msgTag << ":" + tmpl + ":" << "user-end" << ":" << userEnd << std::endl;
ss << msgTag << ":" + tmpl + ":" << "assistant-begin" << ":" << assistantBegin << std::endl;
ss << msgTag << ":" + tmpl + ":" << "assistant-prefix" << ":" << assistantPrefix << std::endl;
ss << msgTag << ":" + tmpl + ":" << "assistant-suffix" << ":" << assistantSuffix << std::endl;
ss << msgTag << ":" + tmpl + ":" << "assistant-end" << ":" << assistantEnd << std::endl;
ss << msgTag << ":" + tmpl + ":" << K_REVERSE_PROMPT << ":" << reversePrompt << std::endl;
ss << msgTag << ":" + tmpl + ":" << K_SYSTEMUSER_SYSTEM_HAS_SUFFIX << ":" << systemHasSuffix << std::endl;
ss << msgTag << ":" + tmpl + ":" << K_SYSTEMUSER_SYSTEM_HAS_END << ":" << systemHasEnd << std::endl;
ss << msgTag << ":" + tmpl + ":" << K_SYSTEMUSER_1ST_USER_HAS_BEGIN << ":" << userHasBegin << std::endl;
ss << msgTag << ":" + tmpl + ":" << K_SYSTEMUSER_1ST_USER_HAS_PREFIX << ":" << userHasPrefix << std::endl;
if (!userEnd.empty()) {
LOG_TEELN("WARN:CT:%s:User-End seems to be set to [%s], do cross check if this is proper and needed", msgTag.c_str(), userEnd.c_str());
}
if (!assistantBegin.empty()) {
LOG_TEELN("WARN:CT:%s:Assistant-Begin seems to be set to [%s], do cross check if this is proper and needed", msgTag.c_str(), assistantBegin.c_str());
}
return true;
}
/**
* For the specified chat-template, get the value associated with the specified key/field.
*/
template <typename SupportedDataType>
SupportedDataType tmpl_getkey(const std::string &tmpl, const std::string &key, const SupportedDataType &defaultValue) {
return get_value(tmpl, {key}, defaultValue, "CTTmplGetKey");
}
/**
* For the specified chat-template and the role within, cumulate the values of the specified keys/fields
* and return the same.
*/
std::string tmpl_role_getkeys(const std::string &tmpl, const std::string &role, const std::vector<std::string> &keys) {
std::string got = "";
std::string sKeys = "";
for(auto key: keys) {
got += get_value<std::string>(tmpl, {role, key}, "", "CTTmplRoleGetKeys");
sKeys += "+";
sKeys += key;
}
LDBUG_LN("DBUG:CT:%s:%s:%s:%s:%s", __func__, tmpl.c_str(), role.c_str(), sKeys.c_str(), got.c_str());
return got;
}
/**
* Given the template standard and a bunch of messages including their roles, this returns
* tagged messages, subPartsTypes string and subPartsLens vector. The returned subParts
* types string and lens vector help identify the parts of the tagged msgs string,
* which relate to passed msgs and added tags.
*
* * a string containing the tagged messages
* * global-begin + 1 or more [[role-begin] + [role-prefix] + msg + [role-suffix] +[role-end]] + global-end
* * a string where the chars contain info about
* type of sub-strings/parts that make up the tagged messages string.
* * a vector of ints, which give the length of each part in the tagged messages string.
*
* If a combination of system-user messages is passed, then tags between the 1st system and
* the 1st user message, is based on the flags set wrt the corresponding template standard.
* If you dont want this behaviour, pass non 0 values wrt the optional cntSystemMsgCnt and
* cntUserMsgCnt arguments.
*/
bool chaton_tmpl_apply_ex(
const std::string &tmpl,
const std::vector<const llama_chat_message *> &msgs,
bool alertAssistantAtEnd,
bool applyGlobalIfAny,
std::string &tagged,
std::string &types,
std::vector<int32_t> &lens,
int curSystemMsgCnt = 0,
int curUserMsgCnt = 0
) {
if (!tmpl_exists(tmpl)) {
return false;
}
ChatParts cp = {};
if (applyGlobalIfAny) {
std::string globalBegin = tmpl_role_getkeys(tmpl, K_GLOBAL, {K_BEGIN});
cp.add_part(ChatParts::S, globalBegin);
}
int cntSystem = curSystemMsgCnt;
int cntUser = curUserMsgCnt;
int cntOthers = 0;
for(const auto msg: msgs) {
auto role = msg->role;
auto content = msg->content;
std::string begin = tmpl_role_getkeys(tmpl, role, {K_BEGIN});
auto prefix = tmpl_role_getkeys(tmpl, role, {K_PREFIX});
auto suffix = tmpl_role_getkeys(tmpl, role, {K_SUFFIX});
auto end = tmpl_role_getkeys(tmpl, role, {K_END});
if (role == K_SYSTEM) {
cntSystem += 1;
cp.add_part(ChatParts::S, begin);
cp.add_part(ChatParts::S, prefix);
} else if (role == K_USER) {
cntUser += 1;
if ((cntSystem == 1) && (cntUser == 1)) {
if (tmpl_getkey(tmpl, K_SYSTEMUSER_1ST_USER_HAS_BEGIN, true)) {
cp.add_part(ChatParts::S, begin);
}
if (tmpl_getkey(tmpl, K_SYSTEMUSER_1ST_USER_HAS_PREFIX, true)) {
cp.add_part(ChatParts::S, prefix);
}
} else {
cp.add_part(ChatParts::S, begin);
cp.add_part(ChatParts::S, prefix);
}
} else {
cntOthers += 1;
cp.add_part(ChatParts::S, begin);
cp.add_part(ChatParts::S, prefix);
}
cp.add_part(ChatParts::N, content);
if (role == K_SYSTEM) {
if (cntSystem == 1) {
if (tmpl_getkey(tmpl, K_SYSTEMUSER_SYSTEM_HAS_SUFFIX, true)) {
cp.add_part(ChatParts::S, suffix);
}
if (tmpl_getkey(tmpl, K_SYSTEMUSER_SYSTEM_HAS_END, true)) {
cp.add_part(ChatParts::S, end);
}
} else {
cp.add_part(ChatParts::S, suffix);
cp.add_part(ChatParts::S, end);
}
} else {
cp.add_part(ChatParts::S, suffix);
cp.add_part(ChatParts::S, end);
}
}
if (alertAssistantAtEnd) {
auto assistantBeginPrefix = tmpl_role_getkeys(tmpl, K_ASSISTANT, {K_BEGIN, K_PREFIX});
cp.add_part(ChatParts::S, assistantBeginPrefix);
}
if (applyGlobalIfAny) {
auto globalEnd = tmpl_role_getkeys(tmpl, K_GLOBAL, {K_END});
cp.add_part(ChatParts::S, globalEnd);
}
LDBUG_LN("DBUG:CT:%s", cp.dump("INFO:ChatOnTmplApplyEx").c_str());
tagged = cp.str();
LOGLN("DBUG:CT:%s:%s:%s", __func__, tmpl.c_str(), tagged.c_str());
LOGLN("DBUG:CT:%s:%s:CntSys[%d]:CntUsr[%d]:CntOthers[%d]", __func__, tmpl.c_str(), cntSystem, cntUser, cntOthers);
types = cp.get_partstypes();
lens = cp.get_partslens();
return true;
}
};
#include "chaton_meta.hpp"
@ -313,7 +522,7 @@ public:
#ifdef CHATON_JSON
template <typename SupportedType>
inline SupportedType json_get(json &j, std::vector<std::string> keys, const std::string &msgTag) {
inline SupportedType json_get(json &j, const std::vector<std::string_view> &keys, const std::string &msgTag) {
json curJ = j;
std::stringstream skey;
int i = 0;
@ -325,7 +534,7 @@ inline SupportedType json_get(json &j, std::vector<std::string> keys, const std:
curJ = curJ[key];
} else {
std::stringstream ss;
ss << "ERRR:ChatON:" << __func__ << ":" << msgTag << ":Key [" << skey.str() << "] is missing";
ss << "ERRR:ChatON:" << __func__ << ":" << msgTag << ":KeyChain [" << skey.str() << "] is missing";
throw std::runtime_error(ss.str());
}
}
@ -394,203 +603,39 @@ inline bool chaton_meta_load(const std::string &fname) {
inline bool chaton_tmpl_exists(const std::string &tmpl) {
if (!gCT.group_exists(tmpl)) {
LOG_TEELN("WARN:%s: tmpl[%s] not found...", __func__, tmpl.c_str());
return false;
}
return true;
return gCT.tmpl_exists(tmpl);
}
inline std::string chaton_tmpl_role_kv(const std::string &tmpl, const std::string &role, const std::vector<std::string> &keys) {
std::string got = "";
std::string sKeys = "";
for(auto key: keys) {
got += gCT.get_value<std::string>(tmpl, {role, key}, "");
sKeys += "+";
sKeys += key;
}
LOGLN("DBUG:%s:%s:%s:%s:%s", __func__, tmpl.c_str(), role.c_str(), sKeys.c_str(), got.c_str());
return got;
inline std::string chaton_tmpl_role_getkeys(const std::string &tmpl, const std::string &role, const std::vector<std::string> &keys) {
return gCT.tmpl_role_getkeys(tmpl, role, keys);
}
inline std::string chaton_tmpl_kv(const std::string &tmpl, const std::string &key) {
std::string got = gCT.get_value<std::string>(tmpl, {key}, "");
LOGLN("DBUG:%s:%s:%s:%s", __func__, tmpl.c_str(), key.c_str(), got.c_str());
return got;
inline std::string chaton_tmpl_getkey_str(const std::string &tmpl, const std::string &key) {
return gCT.tmpl_getkey<std::string>(tmpl, {key}, "");
}
inline bool chaton_tmpl_kv_bool(const std::string &tmpl, const std::string &key) {
bool got = gCT.get_value(tmpl, {key}, false);
LOGLN("DBUG:%s:%s:%s:%d", __func__, tmpl.c_str(), key.c_str(), got);
return got;
}
// Given the template standard, role and a message, this returns
// a tagged message, types string and lens vector wrt the parts that make up the returned string
//
// * a string containing the tagged message
// * role-(begin+prefix) + msg + role-(suffix+end)
// * a string where the chars contain info about
// type of sub-strings/parts that make up the tagged message.
// * a vector of ints, which give the length of each part in the tagged message.
inline bool chaton_tmpl_apply_single_ex(
const std::string &tmpl,
const std::string &role,
const std::string &content,
std::string &tagged,
std::string &types,
std::vector<int32_t> &lens
) {
if (!chaton_tmpl_exists(tmpl)) {
return false;
}
ChatParts cp = {};
std::string beginPrefix = chaton_tmpl_role_kv(tmpl, role, {K_BEGIN, K_PREFIX});
std::string suffixEnd = chaton_tmpl_role_kv(tmpl, role, {K_SUFFIX, K_END});
cp.add_part(ChatParts::S, beginPrefix);
cp.add_part(ChatParts::N, content);
cp.add_part(ChatParts::S, suffixEnd);
cp.dump();
tagged = cp.str();
LOGLN("DBUG:%s:%s:%s:%s", __func__, tmpl.c_str(), role.c_str(), tagged.c_str());
types = cp.get_partstypes();
lens = cp.get_partslens();
return true;
}
// Given the template standard, role and a message, this returns the tagged message.
//
// * a string containing the tagged message
// * role-(begin+prefix) + msg + role-(suffix+end)
inline size_t chaton_tmpl_apply_single(
const std::string &tmpl,
const std::string &role,
const std::string &content,
std::string &tagged
) {
std::string types;
std::vector<int32_t> lens;
if (!chaton_tmpl_apply_single_ex(tmpl, role, content, tagged, types, lens)) {
return -1;
}
return tagged.size();
}
/**
* Apply chat-handshake-template for the specified template standard and role.
* If the passed char array is smaller than that required for the tagged message,
* * part of the tagged message which fits within dest buffer is copied
* * the returned value, indicates the size of the actual tagged message
* NOTE:
* * ideally the passed char array should be able to fit the tagged message+0|null char.
* * if the return value from this function is larger than or equal to destLength,
* then you will have to increase the size of the dest buffer, and call this
* function a second time, to ensure that one gets the full tagged message.
*/
inline size_t chat_tmpl_apply_single_capi(
const char *tmpl,
const char *role,
const char *content,
char *dest,
const size_t destLength
) {
std::string tagged;
auto taggedLength = chaton_tmpl_apply_single(tmpl, role, content, tagged);
if (taggedLength <= 0) {
return taggedLength;
}
if (dest && (destLength > 0)) {
strlcpy(dest, tagged.c_str(), destLength);
}
return taggedLength;
inline bool chaton_tmpl_getkey_bool(const std::string &tmpl, const std::string &key) {
return gCT.tmpl_getkey<bool>(tmpl, {key}, false);
}
// Given the template standard and a bunch of messages including their roles, this returns
// tagged messages, types string and lens vector. Returned types string and lens vector help
// identify the parts of the tagged msgs string, which relate to passed msgs and added tags.
// the tagged messages as a string.
// global-begin + 1 or more [[role-begin] + [role-prefix] + msg + [role-suffix] +[role-end]] + global-end
//
// * a string containing the tagged messages
// * global-begin + 1 or more [[role-begin] + [role-prefix] + msg + [role-suffix] +[role-end]] + global-end
// * a string where the chars contain info about
// type of sub-strings/parts that make up the tagged messages string.
// * a vector of ints, which give the length of each part in the tagged messages string.
//
// if a combination of system-user messages is passed, then tags between the system
// and the 1st user message, is based on the flags set wrt the corresponding template standard.
// Additionally also return info about the parts that make up the tagged message.
inline bool chaton_tmpl_apply_ex(
const std::string &tmpl,
const std::vector<const llama_chat_message *> &msgs,
bool alertAssistantAtEnd,
bool applyGlobalIfAny,
std::string &tagged,
std::string &types,
std::vector<int32_t> &lens
std::vector<int32_t> &lens,
int curSystemMsgCnt = 0,
int curUserMsgCnt = 0
) {
if (!chaton_tmpl_exists(tmpl)) {
return false;
}
ChatParts cp = {};
std::string globalBegin = chaton_tmpl_role_kv(tmpl, K_GLOBAL, {K_BEGIN});
cp.add_part(ChatParts::S, globalBegin);
int cntSystem = 0;
int cntUser = 0;
int cntOthers = 0;
for(const auto msg: msgs) {
auto role = msg->role;
auto content = msg->content;
std::string begin = chaton_tmpl_role_kv(tmpl, role, {K_BEGIN});
auto prefix = chaton_tmpl_role_kv(tmpl, role, {K_PREFIX});
auto suffix = chaton_tmpl_role_kv(tmpl, role, {K_SUFFIX});
auto end = chaton_tmpl_role_kv(tmpl, role, {K_END});
if (role == K_SYSTEM) {
cntSystem += 1;
cp.add_part(ChatParts::S, begin);
cp.add_part(ChatParts::S, prefix);
} else if (role == K_USER) {
cntUser += 1;
if ((cntSystem == 1) && (cntUser == 1)) {
if (chaton_tmpl_kv_bool(tmpl, K_SYSTEMUSER_1ST_USER_HAS_BEGIN)) {
cp.add_part(ChatParts::S, begin);
}
if (chaton_tmpl_kv_bool(tmpl, K_SYSTEMUSER_1ST_USER_HAS_PREFIX)) {
cp.add_part(ChatParts::S, prefix);
}
} else {
cp.add_part(ChatParts::S, begin);
cp.add_part(ChatParts::S, prefix);
}
} else {
cntOthers += 1;
cp.add_part(ChatParts::S, begin);
cp.add_part(ChatParts::S, prefix);
}
cp.add_part(ChatParts::N, content);
if (role == K_SYSTEM) {
if (chaton_tmpl_kv_bool(tmpl, K_SYSTEMUSER_SYSTEM_HAS_SUFFIX)) {
cp.add_part(ChatParts::S, suffix);
}
if (chaton_tmpl_kv_bool(tmpl, K_SYSTEMUSER_SYSTEM_HAS_END)) {
cp.add_part(ChatParts::S, end);
}
} else {
cp.add_part(ChatParts::S, suffix);
cp.add_part(ChatParts::S, end);
}
}
if (alertAssistantAtEnd) {
auto assistantBeginPrefix = chaton_tmpl_role_kv(tmpl, K_ASSISTANT, {K_BEGIN, K_PREFIX});
cp.add_part(ChatParts::S, assistantBeginPrefix);
}
auto globalEnd = chaton_tmpl_role_kv(tmpl, K_GLOBAL, {K_END});
cp.add_part(ChatParts::S, globalEnd);
cp.dump();
tagged = cp.str();
LOGLN("DBUG:%s:%s:%s", __func__, tmpl.c_str(), tagged.c_str());
LOGLN("DBUG:%s:%s:CntSys[%d]:CntUsr[%d]:CntOthers[%d]", __func__, tmpl.c_str(), cntSystem, cntUser, cntOthers);
types = cp.get_partstypes();
lens = cp.get_partslens();
return true;
return gCT.chaton_tmpl_apply_ex(tmpl, msgs, alertAssistantAtEnd, applyGlobalIfAny, tagged, types, lens, curSystemMsgCnt, curUserMsgCnt);
}
// Given the template standard and a bunch of messages including their roles, this returns
@ -600,11 +645,36 @@ inline int32_t chaton_tmpl_apply(
const std::string &tmpl,
const std::vector<const llama_chat_message *> &msgs,
bool alertAssistantAtEnd,
bool applyGlobalIfAny,
std::string &tagged
) {
std::string types;
std::vector<int32_t> lens;
if (!chaton_tmpl_apply_ex(tmpl, msgs, alertAssistantAtEnd, tagged, types, lens)) {
if (!chaton_tmpl_apply_ex(tmpl, msgs, alertAssistantAtEnd, applyGlobalIfAny, tagged, types, lens)) {
return -1;
}
return tagged.size();
}
const int BYPASS_MSGCNT = 101;
//
// Given the template standard, role and a message, this creates the tagged message.
//
// string containing the tagged message
// * role-(begin+prefix) + msg + role-(suffix+end)
//
inline size_t chaton_tmpl_apply_single(
const std::string &tmpl,
const std::string &role,
const std::string &content,
bool alertAssistantAtEnd,
bool applyGlobalIfAny,
std::string &tagged
) {
std::string types;
std::vector<int32_t> lens;
llama_chat_message cm {role.c_str(), content.c_str()};
if (!chaton_tmpl_apply_ex(tmpl, {&cm}, alertAssistantAtEnd, applyGlobalIfAny, tagged, types, lens, BYPASS_MSGCNT, BYPASS_MSGCNT)) {
return -1;
}
return tagged.size();
@ -639,7 +709,7 @@ inline int32_t chaton_tmpl_apply_capi(
vMsgs.push_back(&msgs[i]);
}
std::string taggedMsgs;
int32_t taggedLength = chaton_tmpl_apply(tmpl, vMsgs, alertAssistantAtEnd, taggedMsgs);
int32_t taggedLength = chaton_tmpl_apply(tmpl, vMsgs, alertAssistantAtEnd, true, taggedMsgs);
if (taggedLength < 0) {
return taggedLength;
}
@ -684,7 +754,7 @@ inline int32_t chaton_tmpl_apply_ex_capi(
std::string taggedMsgs;
std::string types;
std::vector<int32_t> lens;
if (!chaton_tmpl_apply_ex(tmpl, vMsgs, alertAssistantAtEnd, taggedMsgs, types, lens)) {
if (!chaton_tmpl_apply_ex(tmpl, vMsgs, alertAssistantAtEnd, true, taggedMsgs, types, lens)) {
return -1;
}
int32_t taggedLength = taggedMsgs.size();
@ -706,7 +776,7 @@ inline int32_t chaton_tmpl_apply_ex_capi(
return taggedLength;
}
// Copied from common.cpp
// Copied from common.cpp, updated wrt model and logging flow.
inline std::vector<llama_token> chaton_llama_tokenize(
const struct llama_model * model,
const std::string & text,
@ -761,74 +831,29 @@ inline std::vector<llama_token> chaton_llama_tokenize_ex(
/**
* if tmpl is
* * empty string, then dump the full loaded chaton-meta
* * chaton-template-id, then dump contents related to that specific chat-handshake-template-standard
* NOTE: It uses the exception raising get_value to check if the tags related keys are present
* wrt the specified template-standard/model-id or not.
* Dump the full loaded chaton templates data
* Additionally if a chaton-template-id is specified
* dump contents related to that specific chat-handshake-template-standard
* NOTE: It uses the exception raising get_value to check if all the required
* keys/fields are present wrt the specified template-standard/model-id or not.
*/
inline bool _chaton_meta_dump(std::string &tmpl) {
if (!tmpl.empty()) {
if (!gCT.group_exists(tmpl)) {
LOGXLN("ERRR:%s:Specified template-id [%s] not found", __func__, tmpl.c_str());
return false;
}
inline bool _chaton_meta_validate_dump(std::string &tmpl) {
LOGXLN("\n\nINFO:%s:%s:\n%s", __func__, tmpl.c_str(), gCT.dump(tmpl, "INFO:ChatOnMetaValidateDump:").c_str());
if (tmpl.empty()) {
return true;
}
LOGXLN("\n\nINFO:%s:%s:\n%s", __func__, tmpl.c_str(), gCT.dump(tmpl, "INFO:ChatOnMetaDump:").c_str());
if (!tmpl.empty()) {
std::string globalBegin = gCT.get_value<std::string>(tmpl, { K_GLOBAL, K_BEGIN });
std::string globalEnd = gCT.get_value<std::string>(tmpl, { K_GLOBAL, K_END });
std::string systemBegin = gCT.get_value<std::string>(tmpl, { K_SYSTEM, K_BEGIN });
std::string systemPrefix = gCT.get_value<std::string>(tmpl, { K_SYSTEM, K_PREFIX });
std::string systemSuffix = gCT.get_value<std::string>(tmpl, { K_SYSTEM, K_SUFFIX });
std::string systemEnd = gCT.get_value<std::string>(tmpl, { K_SYSTEM, K_END });
std::string userBegin = gCT.get_value<std::string>(tmpl, { K_USER, K_BEGIN });
std::string userPrefix = gCT.get_value<std::string>(tmpl, { K_USER, K_PREFIX });
std::string userSuffix = gCT.get_value<std::string>(tmpl, { K_USER, K_SUFFIX });
std::string userEnd = gCT.get_value<std::string>(tmpl, { K_USER, K_END });
std::string assistantBegin = gCT.get_value<std::string>(tmpl, { K_ASSISTANT, K_BEGIN });
std::string assistantPrefix = gCT.get_value<std::string>(tmpl, { K_ASSISTANT, K_PREFIX });
std::string assistantSuffix = gCT.get_value<std::string>(tmpl, { K_ASSISTANT, K_SUFFIX });
std::string assistantEnd = gCT.get_value<std::string>(tmpl, { K_ASSISTANT, K_END });
std::string reversePrompt = gCT.get_value<std::string>(tmpl, { K_REVERSE_PROMPT });
bool systemHasSuffix = gCT.get_value<bool>(tmpl, { K_SYSTEMUSER_SYSTEM_HAS_SUFFIX });
bool systemHasEnd = gCT.get_value<bool>(tmpl, { K_SYSTEMUSER_SYSTEM_HAS_END });
bool userHasBegin = gCT.get_value<bool>(tmpl, { K_SYSTEMUSER_1ST_USER_HAS_BEGIN });
bool userHasPrefix = gCT.get_value<bool>(tmpl, { K_SYSTEMUSER_1ST_USER_HAS_PREFIX });
LOGXLN("INFO:%s:%s:%s", __func__, "global->begin", globalBegin.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "global->end", globalEnd.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "system->begin", systemBegin.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "system->prefix", systemPrefix.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "system->suffix", systemSuffix.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "system->end", systemEnd.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "user->begin", userBegin.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "user->prefix", userPrefix.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "user->suffix", userSuffix.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "user->end", userEnd.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "assistant->begin", assistantBegin.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "assistant->prefix", assistantPrefix.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "assistant->suffix", assistantSuffix.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, "assistant->end", assistantEnd.c_str());
LOGXLN("INFO:%s:%s:%s", __func__, K_REVERSE_PROMPT, reversePrompt.c_str());
LOGXLN("INFO:%s:%s:%d", __func__, K_SYSTEMUSER_SYSTEM_HAS_SUFFIX, systemHasSuffix);
LOGXLN("INFO:%s:%s:%d", __func__, K_SYSTEMUSER_SYSTEM_HAS_END, systemHasEnd);
LOGXLN("INFO:%s:%s:%d", __func__, K_SYSTEMUSER_1ST_USER_HAS_BEGIN, userHasBegin);
LOGXLN("INFO:%s:%s:%d", __func__, K_SYSTEMUSER_1ST_USER_HAS_PREFIX, userHasPrefix);
if (!userEnd.empty()) {
LOG_TEELN("WARN:%s:User->End seems to be set to [%s], do cross check if this is proper and needed", __func__, userEnd.c_str());
}
if (!assistantBegin.empty()) {
LOG_TEELN("WARN:%s:Assistant->Begin seems to be set to [%s], do cross check if this is proper and needed", __func__, assistantBegin.c_str());
}
std::stringstream ss;
if (gCT.tmpl_basiccheck(tmpl, ss, "INFO:ChatOnMetaValidateDump")) {
LOGXLN("%s", ss.str().c_str());
} else {
return false;
}
return true;
}
/**
* Verify that specified chaton-template-id contains required fields using meta-dump
* Verify that specified chaton-template-id contains required fields using meta-validate-dump
*/
inline bool chaton_meta_ok(std::string &tmpl) {
return _chaton_meta_dump(tmpl);
return _chaton_meta_validate_dump(tmpl);
}

View File

@ -56,7 +56,6 @@
#include "groupkv.hpp"
#define SC_DEBUG
#undef SC_DEBUG_VERBOSE
#undef SC_STR_OVERSMART

View File

@ -266,7 +266,7 @@ int main(int argc, char ** argv) {
params.prompt = "<|im_start|>system\n" + params.prompt + "<|im_end|>";
}
if (params.chaton) {
chaton_tmpl_apply_single(params.chaton_template_id, K_SYSTEM, params.prompt, params.prompt);
chaton_tmpl_apply_single(params.chaton_template_id, K_SYSTEM, params.prompt, false, false, params.prompt);
}
embd_inp = ::llama_tokenize(ctx, params.prompt, true, true);
} else {
@ -380,13 +380,13 @@ int main(int argc, char ** argv) {
}
// chaton mode
const auto chaton_assitant_prefix = ::llama_tokenize(ctx, chaton_tmpl_role_kv(params.chaton_template_id, K_ASSISTANT, {K_BEGIN, K_PREFIX}), false, true);
const auto chaton_assitant_prefix = ::llama_tokenize(ctx, chaton_tmpl_role_getkeys(params.chaton_template_id, K_ASSISTANT, {K_BEGIN, K_PREFIX}), false, true);
if (params.chaton) {
params.interactive = true; // may remove later, by requiring user to explicitly request interactive mode
params.interactive_first = true;
params.input_prefix = chaton_tmpl_role_kv(params.chaton_template_id, K_USER, {K_BEGIN, K_PREFIX});
params.input_suffix = chaton_tmpl_role_kv(params.chaton_template_id, K_USER, {K_SUFFIX, K_END});
params.antiprompt.emplace_back(chaton_tmpl_kv(params.chaton_template_id, K_REVERSE_PROMPT));
params.input_prefix = chaton_tmpl_role_getkeys(params.chaton_template_id, K_USER, {K_BEGIN, K_PREFIX});
params.input_suffix = chaton_tmpl_role_getkeys(params.chaton_template_id, K_USER, {K_SUFFIX, K_END});
params.antiprompt.emplace_back(chaton_tmpl_getkey_str(params.chaton_template_id, K_REVERSE_PROMPT));
}
// enable interactive mode if interactive start is specified