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
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:
@@ -0,0 +1,100 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/Tencent/WeKnora/internal/agent"
|
||||
"github.com/Tencent/WeKnora/internal/models/chat"
|
||||
"github.com/Tencent/WeKnora/internal/types"
|
||||
)
|
||||
|
||||
type wikiLiveChatProvider interface{ chat.Chat }
|
||||
|
||||
type wikiLimitedLiveChat struct {
|
||||
wikiLiveChatProvider
|
||||
calls int
|
||||
limit int
|
||||
directory string
|
||||
}
|
||||
|
||||
func (m *wikiLimitedLiveChat) Chat(ctx context.Context, messages []chat.Message, options *chat.ChatOptions) (*types.ChatResponse, error) {
|
||||
if m.calls >= m.limit {
|
||||
return nil, errors.New("live provider request budget exhausted")
|
||||
}
|
||||
m.calls++
|
||||
response, err := m.wikiLiveChatProvider.Chat(ctx, messages, options)
|
||||
if err == nil && response != nil {
|
||||
path := filepath.Join(m.directory, "response-private-"+time.Now().UTC().Format("20060102T150405.000000000")+".json")
|
||||
if os.WriteFile(path, []byte(response.Content), 0600) != nil {
|
||||
return nil, errors.New("could not preserve private live diagnostic response")
|
||||
}
|
||||
}
|
||||
return response, err
|
||||
}
|
||||
|
||||
// Explicit opt-in only. The private fixture contains the configured model and
|
||||
// one read-only source snapshot. It makes one provider invocation by default;
|
||||
// separately authorized recovery mode has a hard two-invocation limit. There
|
||||
// is no database writer, and output is counts only. Never enable this through
|
||||
// the default test suite or pass model secrets on the command line.
|
||||
func TestWikiCitationLiveSingleBatch(t *testing.T) {
|
||||
path := os.Getenv("WIKI_CITATION_LIVE_FIXTURE")
|
||||
if path == "" {
|
||||
t.Skip("requires an explicitly authorized private source/model fixture")
|
||||
}
|
||||
var fixture struct {
|
||||
Model types.Model `json:"model"`
|
||||
Candidates combinedExtraction `json:"candidates"`
|
||||
Chunks []*types.Chunk `json:"chunks"`
|
||||
AESKey string `json:"aes_key"`
|
||||
}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil || json.Unmarshal(data, &fixture) != nil {
|
||||
t.Fatal("could not read the private live-test fixture")
|
||||
}
|
||||
if fixture.AESKey != "" {
|
||||
t.Setenv("SYSTEM_AES_KEY", fixture.AESKey)
|
||||
}
|
||||
parameters, _ := json.Marshal(fixture.Model.Parameters)
|
||||
if fixture.Model.Parameters.Scan(parameters) != nil || fixture.Model.Parameters.APIKey == "" {
|
||||
t.Fatal("live-test configured model credentials unavailable")
|
||||
}
|
||||
remote, err := chat.NewRemoteChat(chat.ConfigFromModel(&fixture.Model, "", ""))
|
||||
if err != nil {
|
||||
t.Fatal("live-test model initialization failed; details suppressed")
|
||||
}
|
||||
candidates := renderCandidateSlugsXML(fixture.Candidates.Entities, fixture.Candidates.Concepts)
|
||||
encoded, handles := encodeWikiCitationCandidates(candidates)
|
||||
batches := splitChunksIntoCitationBatches(fixture.Chunks)
|
||||
if len(batches) == 0 {
|
||||
t.Fatal("live-test fixture has no citation batches")
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Minute)
|
||||
defer cancel()
|
||||
started := time.Now()
|
||||
model := &wikiLimitedLiveChat{wikiLiveChatProvider: remote, limit: 1, directory: filepath.Dir(path)}
|
||||
var parsed citationBatchResult
|
||||
if os.Getenv("WIKI_CITATION_LIVE_ALLOW_REPAIR") == "1" {
|
||||
model.limit = 2
|
||||
parsed, err = (&wikiIngestService{}).classifyCitationBatch(ctx, model, candidates, batches[0], "Chinese", true)
|
||||
} else {
|
||||
var raw string
|
||||
raw, err = (&wikiIngestService{}).generateWithTemplateRequest(ctx, model, agent.WikiChunkCitationPrompt, map[string]string{
|
||||
"CandidateSlugs": encoded, "ChunksXML": renderChunksXML(batches[0]), "Language": "Chinese",
|
||||
}, "", 1)
|
||||
if err == nil {
|
||||
parsed, err = parseWikiCitationBatch(raw, batches[0], wikiCandidateSlugSet(candidates), handles)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("single live citation validation failed (provider_requests=%d candidates=%d first_batch_chunks=%d first_batch_chars=%d); private diagnostic retained", model.calls, handles.Len(), len(batches[0].chunks), batches[0].totalRuneLen)
|
||||
}
|
||||
t.Logf("single_batch_live_pass=true provider_requests=%d provider_request_limit=%d database_writes=0 candidates=%d candidate_chars=%d planned_batches=%d first_batch_chunks=%d first_batch_chars=%d citation_keys=%d declared_new_slugs=%d elapsed_seconds=%.1f",
|
||||
model.calls, model.limit, handles.Len(), len([]rune(encoded)), len(batches), len(batches[0].chunks), batches[0].totalRuneLen, len(parsed.Citations), len(parsed.NewSlugs), time.Since(started).Seconds())
|
||||
}
|
||||
Reference in New Issue
Block a user