Tokenizer implemented

This commit is contained in:
Luxferre
2026-10-13 20:36:29 +03:00
parent 41cfd6f25e
commit 2d21b6f77e
5 changed files with 150 additions and 7 deletions
+47 -1
View File
@@ -30,6 +30,7 @@ typedef struct {
int tc_state_n;
int tc_state_cap;
bool any_toolcall;
int include_usage;
char *final_content; /* non-streaming accumulation */
char *final_reasoning;
tool_call_t *final_tc;
@@ -132,6 +133,31 @@ static void emit_chunk(sse_ctx_t *ctx, const char *role, const char *content,
json_object_put(root);
}
static void emit_usage_chunk(sse_ctx_t *ctx, int prompt_tokens, int completion_tokens) {
json_object *root = json_object_new_object();
json_object_object_add(root, "id", json_object_new_string(ctx->completion_id));
json_object_object_add(root, "object", json_object_new_string("chat.completion.chunk"));
json_object_object_add(root, "created", json_object_new_int64(ctx->created));
json_object_object_add(root, "model", json_object_new_string(ctx->model));
json_object *choices = json_object_new_array();
json_object_object_add(root, "choices", choices);
json_object *usage = json_object_new_object();
json_object_object_add(usage, "prompt_tokens", json_object_new_int(prompt_tokens));
json_object_object_add(usage, "completion_tokens", json_object_new_int(completion_tokens));
json_object_object_add(usage, "total_tokens",
json_object_new_int(prompt_tokens + completion_tokens));
json_object_object_add(root, "usage", usage);
const char *j = json_object_to_json_string(root);
if (j) {
size_t need = strlen(j) + 32;
char *buf = (char *)malloc(need);
int bl = snprintf(buf, need, "data: %s\n\n", j);
write_all(ctx->client_fd, buf, (size_t)bl);
free(buf);
}
json_object_put(root);
}
/* ------------------------------------------------------------------ */
/* SSE line processing */
/* ------------------------------------------------------------------ */
@@ -396,6 +422,18 @@ static void handle_chat(int fd, http_req_t *req, const config_t *cfg) {
}
char *payload = build_gradio_payload(jreq, model);
int prompt_tokens = count_messages_tokens(jreq);
bool include_usage = false;
json_object *so = NULL;
if (json_object_object_get_ex(jreq, "stream_options", &so) &&
json_object_get_type(so) == json_type_object) {
json_object *iu = NULL;
if (json_object_object_get_ex(so, "include_usage", &iu) &&
json_object_get_type(iu) == json_type_boolean)
include_usage = json_object_get_boolean(iu);
}
json_object_put(jreq);
if (!payload) {
send_simple(fd, 400, "Bad Request", "Invalid request: missing messages");
@@ -457,6 +495,7 @@ static void handle_chat(int fd, http_req_t *req, const config_t *cfg) {
ctx.client_fd = fd;
ctx.streaming = stream;
ctx.model = model;
ctx.include_usage = include_usage;
ctx.created = (long)time(NULL);
char uuid[37];
generate_uuid(uuid);
@@ -479,12 +518,19 @@ static void handle_chat(int fd, http_req_t *req, const config_t *cfg) {
if (stream) {
emit_chunk(&ctx, NULL, NULL, NULL, NULL, ctx.any_toolcall ? "tool_calls" : "stop");
if (ctx.include_usage) {
int completion_tokens = tok_count_str(ctx.emitted_content.buf);
completion_tokens += tok_count_str(ctx.emitted_reasoning.buf);
for (int i = 0; i < ctx.tc_state_n; i++)
completion_tokens += tok_count_str(ctx.tc_state[i].prev_args);
emit_usage_chunk(&ctx, prompt_tokens, completion_tokens);
}
const char *done = "data: [DONE]\n\n";
write_all(fd, done, strlen(done));
} else {
char *resp = build_completion_response(ctx.completion_id, ctx.created, ctx.model,
ctx.final_content, ctx.final_reasoning,
ctx.final_tc, ctx.final_n_tc);
ctx.final_tc, ctx.final_n_tc, prompt_tokens);
if (resp) {
send_json(fd, resp);
free(resp);