35 std::string open_marker,
36 std::string close_marker)
38 open_marker_(std::move(open_marker)),
39 close_marker_(std::move(close_marker)),
40 max_marker_len_(std::max(open_marker_.size(), close_marker_.size())) {}
62bool StreamThinkFilter::match_tag(
const std::string& buf,
bool& is_open)
const {
63 if (buf == open_marker_) { is_open =
true;
return true; }
64 if (buf == close_marker_) { is_open =
false;
return true; }
77 if (
byte < 0x80) {
return 1; }
79 if (
byte >= 0xF0) { result = 4; }
80 else if (
byte >= 0xE0) { result = 3; }
81 else if (
byte >= 0xC0) { result = 2; }
97void StreamThinkFilter::emit_utf8_safe(
const char* data,
size_t len) {
98 utf8_buf_.append(data, len);
101 size_t safe = utf8_buf_.size();
102 if (safe == 0) {
return; }
105 auto* buf =
reinterpret_cast<const unsigned char*
>(utf8_buf_.data());
106 for (
size_t i = 1; i <= 4 && i <= safe; ++i) {
107 unsigned char c = buf[safe - i];
111 size_t available = i;
112 if (available <
static_cast<size_t>(expected)) {
121 cb_(utf8_buf_.data(), safe, ud_);
123 utf8_buf_.erase(0, safe);
139void StreamThinkFilter::process_byte(
char c) {
141 if (tag_buf_.empty() && c != open_marker_[0] && c != close_marker_[0]) {
142 if (!in_think_) { emit_utf8_safe(&c, 1); }
146 bool is_open =
false;
147 if (match_tag(tag_buf_, is_open)) {
153 if (tag_buf_.size() > max_marker_len_) {
155 emit_utf8_safe(tag_buf_.data(), tag_buf_.size());
170 if (raw_cb_) { raw_cb_(chunk, len, raw_ud_); }
172 for (
size_t i = 0; i < len; ++i) {
173 process_byte(chunk[i]);
183 if (!tag_buf_.empty() && !in_think_) {
184 emit_utf8_safe(tag_buf_.data(), tag_buf_.size());
188 if (!utf8_buf_.empty()) {
189 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.
Streaming filter that strips a model family's reasoning blocks.