Views
No views yet
Qwen3-VL-Embedding-2Brknn-toolkit2 (v2.2.0).| Embedding Type | Mean Cosine Similarity | Standard Deviation |
|---|---|---|
| Text Embeddings | 0.9591 | 0.0081 |
| Multimodal Image Embeddings | 0.9338 | 0.0244 |
[1, 448, 448, 3] (NHWC representation, uint8).[1, 196, 2048] floats (where 196 represents the visual patch token length).librkllmrt.so (LLM runtime) and librknnrt.so (Vision RKNN runtime). The source file qwen3_embed.cpp must implement the following key elements:llm_cb)1#include "rkllm.h"
2#include <cstdio>
3#include <cstring>
4
5static float* g_output_buffer = nullptr;
6static int g_embedding_dim = 2048;
7
8int llm_cb(RKLLMResult *result, void *userdata, LLMCallState state) {
9 if (state == RKLLM_RUN_NORMAL) {
10 const RKLLMResultLastHiddenLayer &lhl = result->last_hidden_layer;
11 int tokens = lhl.num_tokens;
12 int dim = lhl.embd_size / sizeof(float);
13
14 if (lhl.hidden_states != nullptr && tokens > 0) {
15 // Manual last-token pooling
16 int last_token_idx = tokens - 1;
17 float* last_token_emb = (float*)lhl.hidden_states + last_token_idx * dim;
18
19 // Save the pooled embedding vector
20 memcpy(g_output_buffer, last_token_emb, dim * sizeof(float));
21 }
22 }
23 return 0;
24}1#include "rknn_api.h"
2#include <vector>
3
4bool interleave_vision_outputs(rknn_context ctx, int n_outputs, std::vector<rknn_output> &outputs, float* interleaved_dest) {
5 int model_image_tokens = 196; // Visual patches
6 int embed_size = 2048; // Vector dimension
7
8 for (int i = 0; i < model_image_tokens; i++) {
9 for (int j = 0; j < n_outputs; j++) {
10 float* source_ptr = (float*)(outputs[j].buf) + i * embed_size;
11 float* dest_ptr = interleaved_dest + (i * n_outputs * embed_size) + (j * embed_size);
12 memcpy(dest_ptr, source_ptr, embed_size * sizeof(float));
13 }
14 }
15 return true;
16}<|endoftext|> token (ID 151643) at the end of the user instruction sequence:1void setup_model_and_template(LLMHandle &handle, const char* model_path) {
2 RKLLMParam p = rkllm_createDefaultParam();
3 p.model_path = model_path;
4 p.max_context_len = 512;
5 p.max_new_tokens = 1; // Unused during embedding extraction
6
7 // Define visual markers
8 p.img_start = "<|vision_start|>";
9 p.img_end = "<|vision_end|>";
10 p.img_content = "<|image_pad|>";
11
12 rkllm_init(&handle, &p, llm_cb);
13
14 // Explicitly enforce EOS pooling boundary
15 rkllm_set_chat_template(
16 handle,
17 "Represent the user's input.", // System instruction
18 "<|im_start|>user\n", // Prefix
19 "<|im_end|>\n<|im_start|>assistant\n<|endoftext|>" // Postfix containing EOS
20 );
21}1// For Text Embeddings:
2RKLLMInput inp;
3memset(&inp, 0, sizeof(inp));
4inp.input_type = RKLLM_INPUT_PROMPT;
5inp.role = "user";
6inp.prompt_input = "Your text here";
7
8RKLLMInferParam ip;
9memset(&ip, 0, sizeof(ip));
10ip.mode = RKLLM_INFER_GET_LAST_HIDDEN_LAYER;
11
12rkllm_run(handle, &inp, &ip, nullptr);
13
14// For Multimodal Image Embeddings:
15RKLLMInput inp_img;
16memset(&inp_img, 0, sizeof(inp_img));
17inp_img.input_type = RKLLM_INPUT_MULTIMODAL;
18inp_img.role = "user";
19inp_img.multimodal_input.prompt = "<image>";
20inp_img.multimodal_input.image_embed = interleaved_dest; // Interleaved tokens buffer
21inp_img.multimodal_input.n_image_tokens = 196;
22inp_img.multimodal_input.n_image = 1;
23inp_img.multimodal_input.image_width = 448;
24inp_img.multimodal_input.image_height = 448;
25
26rkllm_run(handle, &inp_img, &ip, nullptr);