42static bool match_tag(
const std::string& buf,
bool& is_open) {
43 if (buf ==
"<think>") { is_open =
true;
return true; }
44 if (buf ==
"</think>") { is_open =
false;
return true; }
57 if (
byte < 0x80) {
return 1; }
59 if (
byte >= 0xF0) { result = 4; }
60 else if (
byte >= 0xE0) { result = 3; }
61 else if (
byte >= 0xC0) { result = 2; }
77void StreamThinkFilter::emit_utf8_safe(
const char* data,
size_t len) {
78 utf8_buf_.append(data, len);
81 size_t safe = utf8_buf_.size();
82 if (safe == 0) {
return; }
85 auto* buf =
reinterpret_cast<const unsigned char*
>(utf8_buf_.data());
86 for (
size_t i = 1; i <= 4 && i <= safe; ++i) {
87 unsigned char c = buf[safe - i];
92 if (available <
static_cast<size_t>(expected)) {
101 cb_(utf8_buf_.data(), safe, ud_);
103 utf8_buf_.erase(0, safe);
119void StreamThinkFilter::process_byte(
char c) {
120 if (tag_buf_.empty() && c !=
'<') {
121 if (!in_think_) { emit_utf8_safe(&c, 1); }
125 bool is_open =
false;
131 if (tag_buf_.size() > 8) {
133 emit_utf8_safe(tag_buf_.data(), tag_buf_.size());
148 if (raw_cb_) { raw_cb_(chunk, len, raw_ud_); }
150 for (
size_t i = 0; i < len; ++i) {
151 process_byte(chunk[i]);
161 if (!tag_buf_.empty() && !in_think_) {
162 emit_utf8_safe(tag_buf_.data(), tag_buf_.size());
166 if (!utf8_buf_.empty()) {
167 cb_(utf8_buf_.data(), utf8_buf_.size(), ud_);
void set_raw_callback(TokenCallback cb, void *ud)
Set optional raw callback (receives ALL tokens unfiltered).
void on_token(const char *chunk, size_t len)
Process a chunk of tokens.
void flush()
Flush any buffered partial tag content.
StreamThinkFilter(TokenCallback cb, void *ud)
Construct with consumer callback.
Activate model on GPU (WARM → ACTIVE).
static int utf8_char_len(unsigned char byte)
Count expected bytes in a UTF-8 sequence from lead byte.
void(*)(const char *, size_t, void *) TokenCallback
Token callback type matching the C API signature.
static bool match_tag(const std::string &buf, bool &is_open)
Check if accumulated buffer matches a think tag.
Streaming filter that strips <think>...</think> blocks.