WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s

This commit is contained in:
yawan
2026-09-22 16:19:06 +08:00
commit f7fc992f57
3929 changed files with 1006607 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
package vlm
import (
"context"
"github.com/Tencent/WeKnora/internal/tracing/langfuse"
)
// langfuseVLM wraps a VLM and reports each Predict call as a Langfuse
// generation. The raw image bytes are NOT uploaded — Langfuse traces are
// designed for text. We include image count and total byte size in the
// metadata, plus the text prompt, which matches how Langfuse's own VLM
// integrations report multimodal calls.
type langfuseVLM struct {
inner VLM
}
func (l *langfuseVLM) GetModelName() string { return l.inner.GetModelName() }
func (l *langfuseVLM) GetModelID() string { return l.inner.GetModelID() }
func (l *langfuseVLM) Predict(ctx context.Context, imgBytes [][]byte, prompt string) (string, error) {
mgr := langfuse.GetManager()
if !mgr.Enabled() {
return l.inner.Predict(ctx, imgBytes, prompt)
}
totalImgSize := 0
for _, b := range imgBytes {
totalImgSize += len(b)
}
genCtx, gen := mgr.StartGeneration(ctx, langfuse.GenerationOptions{
Name: "vlm.predict",
Model: l.inner.GetModelName(),
Input: map[string]interface{}{
"prompt": prompt,
"image_count": len(imgBytes),
},
Metadata: map[string]interface{}{
"model_id": l.inner.GetModelID(),
"image_count": len(imgBytes),
"image_bytes_total": totalImgSize,
},
})
result, err := l.inner.Predict(genCtx, imgBytes, prompt)
// VLMs don't return token usage; approximate prompt tokens for cost
// tracking in Langfuse (users can configure per-model pricing in the UI).
promptTokens := len([]rune(prompt))/4 + 1
outputTokens := len([]rune(result)) / 4
usage := &langfuse.TokenUsage{
Input: promptTokens,
Output: outputTokens,
Total: promptTokens + outputTokens,
Unit: "TOKENS",
}
gen.Finish(result, usage, err)
return result, err
}
// wrapVLMLangfuse applies the Langfuse decorator when the manager is enabled.
func wrapVLMLangfuse(v VLM, err error) (VLM, error) {
if err != nil || v == nil {
return v, err
}
if !langfuse.GetManager().Enabled() {
return v, nil
}
return &langfuseVLM{inner: v}, nil
}