@mupt-ai/dari-router 0.2.3 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +14 -1
- package/dist/anonymous_actions.d.ts +17 -8
- package/dist/anonymous_actions.js +110 -44
- package/dist/anonymous_actions.js.map +1 -1
- package/dist/cache_behavior.js +1 -1
- package/dist/cache_behavior.js.map +1 -1
- package/dist/continuation_state.d.ts +1 -0
- package/dist/continuation_state.js +6 -1
- package/dist/continuation_state.js.map +1 -1
- package/dist/cost.d.ts +1 -0
- package/dist/cost.js +8 -4
- package/dist/cost.js.map +1 -1
- package/dist/eval_score_imputation.d.ts +14 -3
- package/dist/eval_score_imputation.js +82 -59
- package/dist/eval_score_imputation.js.map +1 -1
- package/dist/fixed_turn_cost_config.d.ts +2 -0
- package/dist/fixed_turn_cost_config.js +8 -0
- package/dist/fixed_turn_cost_config.js.map +1 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/jev_client.d.ts +31 -0
- package/dist/jev_client.js +115 -0
- package/dist/jev_client.js.map +1 -0
- package/dist/jev_eval_relevance.d.ts +49 -0
- package/dist/jev_eval_relevance.js +176 -0
- package/dist/jev_eval_relevance.js.map +1 -0
- package/dist/jev_selector.d.ts +3 -27
- package/dist/jev_selector.js +31 -221
- package/dist/jev_selector.js.map +1 -1
- package/dist/model_ids.js +10 -3
- package/dist/model_ids.js.map +1 -1
- package/dist/pi_context.js.map +1 -1
- package/dist/pi_options.js +83 -26
- package/dist/pi_options.js.map +1 -1
- package/dist/pi_output.js +2 -2
- package/dist/pi_output.js.map +1 -1
- package/dist/policy-engine.d.ts +2 -0
- package/dist/policy-engine.js +2 -0
- package/dist/policy-engine.js.map +1 -1
- package/dist/prompts/anonymous_action.md +29 -0
- package/dist/prompts/anonymous_rules.md +5 -0
- package/dist/prompts/custom_rules.md +10 -0
- package/dist/prompts/jev_eval_relevance.json +12 -0
- package/dist/prompts/jev_selector.json +22 -0
- package/dist/prompts/selector.md +21 -0
- package/dist/prompts.d.ts +28 -3
- package/dist/prompts.js +59 -80
- package/dist/prompts.js.map +1 -1
- package/dist/route.d.ts +1 -0
- package/dist/route.js +21 -0
- package/dist/route.js.map +1 -1
- package/dist/routing_history.d.ts +3 -0
- package/dist/routing_history.js +90 -55
- package/dist/routing_history.js.map +1 -1
- package/dist/selector_input.d.ts +0 -2
- package/dist/selector_input.js +15 -7
- package/dist/selector_input.js.map +1 -1
- package/dist/selector_request.d.ts +0 -1
- package/dist/selector_request.js +14 -37
- package/dist/selector_request.js.map +1 -1
- package/dist/selector_truncation.d.ts +0 -1
- package/dist/selector_truncation.js +6 -39
- package/dist/selector_truncation.js.map +1 -1
- package/dist/thinking_level_graph.d.ts +10 -0
- package/dist/thinking_level_graph.js +64 -0
- package/dist/thinking_level_graph.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/package.json +4 -5
- package/dist/jev_router.d.ts +0 -5
- package/dist/jev_router.js +0 -22
- package/dist/jev_router.js.map +0 -1
- package/examples/jev_router.ts +0 -50
package/dist/selector_input.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Builds the selector input: candidate pairs, matched eval scores, cost
|
|
2
2
|
// estimates, the previous decision, and the (image-scrubbed) conversation.
|
|
3
3
|
// The system prompts live in prompts.ts.
|
|
4
|
-
import { createThinkingLevelRatios, resolveRouterEvalScore, } from "./eval_score_imputation.js";
|
|
4
|
+
import { createThinkingLevelRatios, resolveRouterEvalScore, resolveRouterEvalTaskCost, createTaskCostRatios, } from "./eval_score_imputation.js";
|
|
5
5
|
import { isRecord, routingCandidateKey, } from "./types.js";
|
|
6
6
|
const IMAGE_OMITTED_PLACEHOLDER = "<image omitted>";
|
|
7
7
|
// Numbered placeholders name images that travel to the selector out of band
|
|
@@ -45,10 +45,9 @@ export function buildSelectorInput(args) {
|
|
|
45
45
|
}
|
|
46
46
|
: null,
|
|
47
47
|
cost_estimates: args.costEstimates,
|
|
48
|
-
// Only callers that computed lease context provide
|
|
49
|
-
//
|
|
50
|
-
//
|
|
51
|
-
...(args.task !== undefined ? { task: args.task } : {}),
|
|
48
|
+
// Only callers that computed lease context provide it; omitting the key
|
|
49
|
+
// entirely keeps the input byte-identical to the shape before lease
|
|
50
|
+
// history existed, for routers with lease context disabled.
|
|
52
51
|
...(args.leaseHistory !== undefined ? { lease_history: args.leaseHistory } : {}),
|
|
53
52
|
messages: args.messages,
|
|
54
53
|
};
|
|
@@ -75,8 +74,9 @@ function formatImportedEvals(evals, candidates, imputeEvalScores, imputationRefe
|
|
|
75
74
|
]
|
|
76
75
|
: [];
|
|
77
76
|
const thinkingLevelRatios = createThinkingLevelRatios(ratioEvals);
|
|
77
|
+
const taskCostRatios = createTaskCostRatios(ratioEvals);
|
|
78
78
|
return evals.flatMap((evalCard) => {
|
|
79
|
-
const scores = matchingEvalScores(evalCard.scores, candidates, imputeEvalScores, evalCard.min_score, evalCard.max_score, thinkingLevelRatios);
|
|
79
|
+
const scores = matchingEvalScores(evalCard.scores, candidates, imputeEvalScores, evalCard.min_score, evalCard.max_score, thinkingLevelRatios, taskCostRatios);
|
|
80
80
|
if (scores.length === 0)
|
|
81
81
|
return [];
|
|
82
82
|
return [
|
|
@@ -91,7 +91,7 @@ function formatImportedEvals(evals, candidates, imputeEvalScores, imputationRefe
|
|
|
91
91
|
];
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
|
-
function matchingEvalScores(scores, candidates, imputeEvalScores, minScore, maxScore, thinkingLevelRatios) {
|
|
94
|
+
function matchingEvalScores(scores, candidates, imputeEvalScores, minScore, maxScore, thinkingLevelRatios, taskCostRatios) {
|
|
95
95
|
const uniqueCandidates = new Map(candidates.map((candidate) => [routingCandidateKey(candidate), candidate]));
|
|
96
96
|
const resolvedScores = [...uniqueCandidates.values()]
|
|
97
97
|
.map((candidate) => {
|
|
@@ -110,6 +110,13 @@ function matchingEvalScores(scores, candidates, imputeEvalScores, minScore, maxS
|
|
|
110
110
|
const measured = resolved.imputed
|
|
111
111
|
? null
|
|
112
112
|
: (modelScores.find((score) => score.thinking_level === candidate.reasoningEffort) ?? modelScores.find((score) => score.thinking_level == null));
|
|
113
|
+
const costPerTask = resolveRouterEvalTaskCost({
|
|
114
|
+
scores,
|
|
115
|
+
modelId: candidate.model,
|
|
116
|
+
thinkingLevel: candidate.reasoningEffort,
|
|
117
|
+
impute: imputeEvalScores,
|
|
118
|
+
ratios: taskCostRatios,
|
|
119
|
+
});
|
|
113
120
|
return {
|
|
114
121
|
model_id: candidate.model,
|
|
115
122
|
thinking_level: candidate.reasoningEffort,
|
|
@@ -117,6 +124,7 @@ function matchingEvalScores(scores, candidates, imputeEvalScores, minScore, maxS
|
|
|
117
124
|
notes: measured?.notes ?? null,
|
|
118
125
|
...(resolved.imputed ? { imputed: true } : {}),
|
|
119
126
|
...(resolved.sourceModelId ? { source_model_id: resolved.sourceModelId } : {}),
|
|
127
|
+
...(costPerTask === null ? {} : { cost_per_task_usd: costPerTask }),
|
|
120
128
|
};
|
|
121
129
|
})
|
|
122
130
|
.filter((score) => score !== null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector_input.js","sourceRoot":"","sources":["../src/selector_input.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,2EAA2E;AAC3E,yCAAyC;AAEzC,OAAO,EACL,yBAAyB,EACzB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"selector_input.js","sourceRoot":"","sources":["../src/selector_input.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,7 +16,6 @@ export type SelectorRequestArgs = {
|
|
|
16
16
|
} | null;
|
|
17
17
|
selectorModel: string;
|
|
18
18
|
messages: ChatMessage[];
|
|
19
|
-
task?: ChatMessage | null;
|
|
20
19
|
leaseHistory?: SelectorLeaseHistoryEntry[];
|
|
21
20
|
modelFallbackEnabled?: boolean;
|
|
22
21
|
fallbackRequiresDifferentProvider?: boolean;
|
package/dist/selector_request.js
CHANGED
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
import { RouterCoreError } from "./errors.js";
|
|
2
|
-
import {
|
|
2
|
+
import { CUSTOM_RULES_PROMPT, SELECTOR_SYSTEM_PROMPT } from "./prompts.js";
|
|
3
3
|
import { buildSelectorInput, } from "./selector_input.js";
|
|
4
|
-
import { olderMessageChars, trimMessagesFromFront
|
|
4
|
+
import { olderMessageChars, trimMessagesFromFront } from "./selector_truncation.js";
|
|
5
5
|
import { REASONING_EFFORTS } from "./types.js";
|
|
6
|
-
// Builds the selector request, trimming old conversation history first and
|
|
7
|
-
//
|
|
8
|
-
//
|
|
6
|
+
// Builds the selector request, trimming old conversation history first and the
|
|
7
|
+
// latest turn only when necessary. The window size is an explicit input (in
|
|
8
|
+
// characters) so the core stays free of model-registry lookups.
|
|
9
9
|
export function buildSizedSelectorRequest(args) {
|
|
10
10
|
let messages = args.messages;
|
|
11
|
-
let
|
|
12
|
-
const taskExceedsWindow = task !== undefined
|
|
13
|
-
&& task !== null
|
|
14
|
-
&& JSON.stringify(task).length > args.contextWindowChars;
|
|
15
|
-
let built = buildSelectorRequest({ ...args, messages, task });
|
|
11
|
+
let built = buildSelectorRequest({ ...args, messages });
|
|
16
12
|
while (true) {
|
|
17
13
|
const inputChars = selectorRequestInputChars(built.selectorRequest);
|
|
18
14
|
if (inputChars <= args.contextWindowChars)
|
|
@@ -21,43 +17,20 @@ export function buildSizedSelectorRequest(args) {
|
|
|
21
17
|
const removableHistoryChars = olderMessageChars(messages);
|
|
22
18
|
if (removableHistoryChars > 0) {
|
|
23
19
|
const trimmedMessages = trimMessagesFromFront(messages, Math.min(dropChars, removableHistoryChars));
|
|
24
|
-
const messagesBuilt = buildSelectorRequest({ ...args, messages: trimmedMessages
|
|
20
|
+
const messagesBuilt = buildSelectorRequest({ ...args, messages: trimmedMessages });
|
|
25
21
|
if (selectorRequestInputChars(messagesBuilt.selectorRequest) < inputChars) {
|
|
26
22
|
messages = trimmedMessages;
|
|
27
23
|
built = messagesBuilt;
|
|
28
24
|
continue;
|
|
29
25
|
}
|
|
30
26
|
}
|
|
31
|
-
// If the retained task cannot fit the whole window by itself, compact it
|
|
32
|
-
// before touching the latest conversation turn. Smaller tasks keep the
|
|
33
|
-
// previous behavior: the conversation view shrinks first.
|
|
34
|
-
if (taskExceedsWindow && task !== undefined && task !== null) {
|
|
35
|
-
const taskChars = JSON.stringify(task).length;
|
|
36
|
-
const maxTaskDropChars = Math.max(0, taskChars - Math.floor(args.contextWindowChars / 2));
|
|
37
|
-
const trimmedTask = trimTaskMessage(task, Math.min(dropChars, maxTaskDropChars));
|
|
38
|
-
const taskBuilt = buildSelectorRequest({ ...args, messages, task: trimmedTask });
|
|
39
|
-
if (selectorRequestInputChars(taskBuilt.selectorRequest) < inputChars) {
|
|
40
|
-
task = trimmedTask;
|
|
41
|
-
built = taskBuilt;
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
27
|
const trimmedMessages = trimMessagesFromFront(messages, dropChars);
|
|
46
|
-
const messagesBuilt = buildSelectorRequest({ ...args, messages: trimmedMessages
|
|
28
|
+
const messagesBuilt = buildSelectorRequest({ ...args, messages: trimmedMessages });
|
|
47
29
|
if (selectorRequestInputChars(messagesBuilt.selectorRequest) < inputChars) {
|
|
48
30
|
messages = trimmedMessages;
|
|
49
31
|
built = messagesBuilt;
|
|
50
32
|
continue;
|
|
51
33
|
}
|
|
52
|
-
if (task !== undefined && task !== null) {
|
|
53
|
-
const trimmedTask = trimTaskMessage(task, dropChars);
|
|
54
|
-
const taskBuilt = buildSelectorRequest({ ...args, messages, task: trimmedTask });
|
|
55
|
-
if (selectorRequestInputChars(taskBuilt.selectorRequest) < inputChars) {
|
|
56
|
-
task = trimmedTask;
|
|
57
|
-
built = taskBuilt;
|
|
58
|
-
continue;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
34
|
throw new RouterCoreError("configuration", `Selector prompt cannot fit configured context window for ${args.selectorModel}.`, "configuration_error");
|
|
62
35
|
}
|
|
63
36
|
}
|
|
@@ -72,7 +45,6 @@ export function buildSelectorRequest(args) {
|
|
|
72
45
|
previousDecision: args.previousDecision ?? null,
|
|
73
46
|
costEstimates: args.costEstimates ?? null,
|
|
74
47
|
messages: args.messages,
|
|
75
|
-
task: args.task,
|
|
76
48
|
leaseHistory: args.leaseHistory,
|
|
77
49
|
customRules: args.customRules,
|
|
78
50
|
defaultTarget: args.defaultTarget,
|
|
@@ -86,7 +58,12 @@ export function buildSelectorRequest(args) {
|
|
|
86
58
|
selectorRequest: {
|
|
87
59
|
model: args.selectorModel,
|
|
88
60
|
messages: [
|
|
89
|
-
{
|
|
61
|
+
{
|
|
62
|
+
role: "system",
|
|
63
|
+
content: isCustom
|
|
64
|
+
? `${SELECTOR_SYSTEM_PROMPT}\n\n${CUSTOM_RULES_PROMPT}`
|
|
65
|
+
: SELECTOR_SYSTEM_PROMPT,
|
|
66
|
+
},
|
|
90
67
|
{
|
|
91
68
|
role: "user",
|
|
92
69
|
content: JSON.stringify(selectorInput),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector_request.js","sourceRoot":"","sources":["../src/selector_request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"selector_request.js","sourceRoot":"","sources":["../src/selector_request.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { type ChatMessage } from "./types.js";
|
|
2
2
|
export declare function olderMessageChars(messages: ChatMessage[]): number;
|
|
3
3
|
export declare function trimMessagesFromFront(messages: ChatMessage[], dropChars: number): ChatMessage[];
|
|
4
|
-
export declare function trimTaskMessage(task: ChatMessage, dropChars: number): ChatMessage;
|
|
@@ -2,23 +2,23 @@
|
|
|
2
2
|
// conversation; the eventual provider call still receives the full request.
|
|
3
3
|
import { isRecord } from "./types.js";
|
|
4
4
|
const SELECTOR_TRUNCATION_MARKER = "<earlier messages truncated for routing>";
|
|
5
|
-
const TASK_TRUNCATION_MARKER = "\n...[original task truncated for routing]...\n";
|
|
6
|
-
const TASK_OMITTED_PLACEHOLDER = "<original task omitted for routing>";
|
|
7
5
|
const MARKER_MESSAGE = { role: "user", content: SELECTOR_TRUNCATION_MARKER };
|
|
8
6
|
// Maximum removable history while keeping the latest message intact. Sizing
|
|
9
|
-
// uses this before compacting
|
|
7
|
+
// uses this before compacting the latest turn.
|
|
10
8
|
export function olderMessageChars(messages) {
|
|
11
9
|
if (messages.length <= 1)
|
|
12
10
|
return 0;
|
|
13
11
|
return Math.max(0, JSON.stringify(messages).length - JSON.stringify([MARKER_MESSAGE, messages.at(-1)]).length);
|
|
14
12
|
}
|
|
15
|
-
// Drop oldest messages first
|
|
16
|
-
// messages carry
|
|
13
|
+
// Drop the oldest agent messages first: the latest turns carry the routing
|
|
14
|
+
// signal and the user's messages carry their intent, so user messages go,
|
|
15
|
+
// oldest first, only once no older agent message is left.
|
|
17
16
|
export function trimMessagesFromFront(messages, dropChars) {
|
|
18
17
|
const targetLength = Math.max(0, JSON.stringify(messages).length - Math.max(0, dropChars));
|
|
19
18
|
const kept = [...messages];
|
|
20
19
|
while (kept.length > 1 && JSON.stringify([MARKER_MESSAGE, ...kept]).length > targetLength) {
|
|
21
|
-
kept.
|
|
20
|
+
const agentIndex = kept.findIndex((message, index) => index < kept.length - 1 && message.role !== "user");
|
|
21
|
+
kept.splice(agentIndex >= 0 ? agentIndex : 0, 1);
|
|
22
22
|
}
|
|
23
23
|
const marked = [MARKER_MESSAGE, ...kept];
|
|
24
24
|
if (JSON.stringify(marked).length <= targetLength)
|
|
@@ -40,39 +40,6 @@ export function trimMessagesFromFront(messages, dropChars) {
|
|
|
40
40
|
}
|
|
41
41
|
return [MARKER_MESSAGE];
|
|
42
42
|
}
|
|
43
|
-
// The original task normally stays intact even when conversation history is
|
|
44
|
-
// compacted. If that retained task alone exceeds the selector window, preserve
|
|
45
|
-
// both ends so the request and its trailing constraints remain visible.
|
|
46
|
-
export function trimTaskMessage(task, dropChars) {
|
|
47
|
-
const targetLength = Math.max(0, JSON.stringify(task).length - Math.max(0, dropChars));
|
|
48
|
-
if (JSON.stringify(task).length <= targetLength)
|
|
49
|
-
return task;
|
|
50
|
-
const source = trimSourceContent(task);
|
|
51
|
-
if (source === null)
|
|
52
|
-
return { role: task.role, content: TASK_OMITTED_PLACEHOLDER };
|
|
53
|
-
let contentChars = source.length;
|
|
54
|
-
while (contentChars > 0) {
|
|
55
|
-
const candidate = {
|
|
56
|
-
role: task.role,
|
|
57
|
-
content: elideTaskMiddle(source, contentChars),
|
|
58
|
-
};
|
|
59
|
-
const excess = JSON.stringify(candidate).length - targetLength;
|
|
60
|
-
if (excess <= 0)
|
|
61
|
-
return candidate;
|
|
62
|
-
contentChars = Math.max(0, contentChars - excess);
|
|
63
|
-
}
|
|
64
|
-
return { role: task.role, content: TASK_OMITTED_PLACEHOLDER };
|
|
65
|
-
}
|
|
66
|
-
function elideTaskMiddle(value, maxChars) {
|
|
67
|
-
if (value.length <= maxChars)
|
|
68
|
-
return value;
|
|
69
|
-
if (maxChars <= TASK_TRUNCATION_MARKER.length) {
|
|
70
|
-
return TASK_TRUNCATION_MARKER.slice(0, maxChars);
|
|
71
|
-
}
|
|
72
|
-
const retainedChars = maxChars - TASK_TRUNCATION_MARKER.length;
|
|
73
|
-
const prefixChars = Math.ceil(retainedChars / 2);
|
|
74
|
-
return `${value.slice(0, prefixChars)}${TASK_TRUNCATION_MARKER}${value.slice(-(retainedChars - prefixChars))}`;
|
|
75
|
-
}
|
|
76
43
|
function trimSourceContent(message) {
|
|
77
44
|
if (typeof message.content === "string")
|
|
78
45
|
return message.content;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selector_truncation.js","sourceRoot":"","sources":["../src/selector_truncation.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,4EAA4E;AAE5E,OAAO,EAAE,QAAQ,EAAoB,MAAM,YAAY,CAAC;AAExD,MAAM,0BAA0B,GAAG,0CAA0C,CAAC;AAC9E,MAAM,
|
|
1
|
+
{"version":3,"file":"selector_truncation.js","sourceRoot":"","sources":["../src/selector_truncation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReasoningEffort } from "./types.js";
|
|
2
|
+
export type ThinkingLevelObservation = {
|
|
3
|
+
provider: string;
|
|
4
|
+
levels: ReadonlyMap<ReasoningEffort, number>;
|
|
5
|
+
};
|
|
6
|
+
type Graph<Edge> = ReadonlyMap<ReasoningEffort, ReadonlyMap<ReasoningEffort, Edge>>;
|
|
7
|
+
export type ThinkingLevelRatios = ReadonlyMap<string, Graph<number>>;
|
|
8
|
+
export declare function buildThinkingLevelGraphs(observations: readonly ThinkingLevelObservation[]): ThinkingLevelRatios;
|
|
9
|
+
export declare function thinkingLevelRatio(graphs: ThinkingLevelRatios, provider: string, from: ReasoningEffort, to: ReasoningEffort): number | undefined;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Average each directed ratio within its provider. Never pair different models
|
|
2
|
+
// or evals: only levels within a single observation can contribute an edge.
|
|
3
|
+
export function buildThinkingLevelGraphs(observations) {
|
|
4
|
+
const samples = new Map();
|
|
5
|
+
for (const { provider, levels } of observations) {
|
|
6
|
+
const graph = samples.get(provider)
|
|
7
|
+
?? new Map();
|
|
8
|
+
samples.set(provider, graph);
|
|
9
|
+
for (const [from, anchor] of levels) {
|
|
10
|
+
if (!Number.isFinite(anchor) || anchor <= 0)
|
|
11
|
+
continue;
|
|
12
|
+
const edges = graph.get(from) ?? new Map();
|
|
13
|
+
graph.set(from, edges);
|
|
14
|
+
for (const [to, target] of levels) {
|
|
15
|
+
const ratio = target / anchor;
|
|
16
|
+
if (from === to || !Number.isFinite(ratio) || ratio < 0)
|
|
17
|
+
continue;
|
|
18
|
+
const sample = edges.get(to) ?? { sum: 0, count: 0 };
|
|
19
|
+
sample.sum += ratio;
|
|
20
|
+
sample.count += 1;
|
|
21
|
+
edges.set(to, sample);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const graphs = new Map();
|
|
26
|
+
for (const [provider, graph] of samples) {
|
|
27
|
+
const averaged = new Map();
|
|
28
|
+
for (const [from, edges] of graph) {
|
|
29
|
+
averaged.set(from, new Map([...edges].map(([to, { sum, count }]) => [to, sum / count])));
|
|
30
|
+
}
|
|
31
|
+
graphs.set(provider, averaged);
|
|
32
|
+
}
|
|
33
|
+
return graphs;
|
|
34
|
+
}
|
|
35
|
+
// Breadth-first search: direct edges win, otherwise average the products of
|
|
36
|
+
// all shortest paths. A provider with no path has no estimate, not a fallback.
|
|
37
|
+
export function thinkingLevelRatio(graphs, provider, from, to) {
|
|
38
|
+
const graph = graphs.get(provider);
|
|
39
|
+
if (!graph)
|
|
40
|
+
return undefined;
|
|
41
|
+
let frontier = new Map([[from, { sum: 1, count: 1 }]]);
|
|
42
|
+
const visited = new Set([from]);
|
|
43
|
+
while (frontier.size > 0) {
|
|
44
|
+
const next = new Map();
|
|
45
|
+
for (const [level, paths] of frontier) {
|
|
46
|
+
for (const [neighbor, ratio] of graph.get(level) ?? []) {
|
|
47
|
+
if (visited.has(neighbor))
|
|
48
|
+
continue;
|
|
49
|
+
const merged = next.get(neighbor) ?? { sum: 0, count: 0 };
|
|
50
|
+
merged.sum += paths.sum * ratio;
|
|
51
|
+
merged.count += paths.count;
|
|
52
|
+
next.set(neighbor, merged);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const result = next.get(to);
|
|
56
|
+
if (result)
|
|
57
|
+
return result.sum / result.count;
|
|
58
|
+
for (const level of next.keys())
|
|
59
|
+
visited.add(level);
|
|
60
|
+
frontier = next;
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=thinking_level_graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"thinking_level_graph.js","sourceRoot":"","sources":["../src/thinking_level_graph.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mupt-ai/dari-router",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "End-to-end TypeScript framework for routing across LLMs with built-in Pi AI execution and pluggable policies and executors.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"LICENSE"
|
|
56
56
|
],
|
|
57
57
|
"scripts": {
|
|
58
|
-
"build": "tsc -p tsconfig.build.json",
|
|
58
|
+
"build": "tsc -p tsconfig.build.json && cp -R src/prompts dist/",
|
|
59
59
|
"test:package": "bash scripts/test-package.sh",
|
|
60
60
|
"prepublishOnly": "bun run typecheck && bun test && bun run test:package",
|
|
61
61
|
"typecheck": "tsc --noEmit",
|
|
@@ -63,12 +63,11 @@
|
|
|
63
63
|
"example": "bun run examples/create_router.ts",
|
|
64
64
|
"example:pi": "bun run examples/pi_runtime.ts",
|
|
65
65
|
"example:dari-policy": "bun run examples/dari_policy.ts",
|
|
66
|
-
"example:jev": "bun run examples/jev_router.ts",
|
|
67
66
|
"example:decision-pipeline": "bun run examples/basic_route.ts",
|
|
68
67
|
"example:lease-stores": "bun run examples/lease_stores.ts"
|
|
69
68
|
},
|
|
70
69
|
"peerDependencies": {
|
|
71
|
-
"@mupt-ai/pi-ai": ">=
|
|
70
|
+
"@mupt-ai/pi-ai": ">=1.1.0-mupt.1 <2.0.0"
|
|
72
71
|
},
|
|
73
72
|
"peerDependenciesMeta": {
|
|
74
73
|
"@mupt-ai/pi-ai": {
|
|
@@ -76,7 +75,7 @@
|
|
|
76
75
|
}
|
|
77
76
|
},
|
|
78
77
|
"devDependencies": {
|
|
79
|
-
"@mupt-ai/pi-ai": "
|
|
78
|
+
"@mupt-ai/pi-ai": "1.1.0-mupt.2",
|
|
80
79
|
"@types/bun": "^1.3.4",
|
|
81
80
|
"@types/node": "^24.10.2",
|
|
82
81
|
"typescript": "^5.6.3"
|
package/dist/jev_router.d.ts
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { type DariRoutingPolicyOptions } from "./dari_policy.js";
|
|
2
|
-
import type { RoutingPolicy } from "./framework_types.js";
|
|
3
|
-
import { type JevSelectorConfig } from "./jev_selector.js";
|
|
4
|
-
export type CreateJevRouterOptions<Metadata = unknown> = JevSelectorConfig & Omit<DariRoutingPolicyOptions<Metadata>, "selector" | "runtime" | "selectorModel" | "selectorContextWindowChars" | "strategy" | "customConfig">;
|
|
5
|
-
export declare function createJevRouter<Metadata = unknown>(options: CreateJevRouterOptions<Metadata>): RoutingPolicy<Metadata>;
|
package/dist/jev_router.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// Jev Router — TypeSafe's Jev model as the routing policy for a self-hosted
|
|
2
|
-
// createRouter, in place of Dari's trained routing policy. Selection runs against
|
|
3
|
-
// TypeSafe's API with the caller's own TypeSafe key.
|
|
4
|
-
import { createDariRoutingPolicyInternal, } from "./dari_policy.js";
|
|
5
|
-
import { createJevSelector, JEV_SELECTOR_CONTEXT_WINDOW_CHARS, resolveJevSelectorConfig, } from "./jev_selector.js";
|
|
6
|
-
export function createJevRouter(options) {
|
|
7
|
-
const { apiKey, endpoint, model, leaseTurns, timeoutMs, ...policyOptions } = options;
|
|
8
|
-
const config = resolveJevSelectorConfig({
|
|
9
|
-
apiKey,
|
|
10
|
-
...(endpoint === undefined ? {} : { endpoint }),
|
|
11
|
-
...(model === undefined ? {} : { model }),
|
|
12
|
-
...(leaseTurns === undefined ? {} : { leaseTurns }),
|
|
13
|
-
...(timeoutMs === undefined ? {} : { timeoutMs }),
|
|
14
|
-
});
|
|
15
|
-
return createDariRoutingPolicyInternal({
|
|
16
|
-
...policyOptions,
|
|
17
|
-
selectorModel: `typesafe/${config.model}`,
|
|
18
|
-
selectorContextWindowChars: JEV_SELECTOR_CONTEXT_WINDOW_CHARS,
|
|
19
|
-
selector: createJevSelector(config),
|
|
20
|
-
}, true);
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=jev_router.js.map
|
package/dist/jev_router.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"jev_router.js","sourceRoot":"","sources":["../src/jev_router.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,kFAAkF;AAClF,qDAAqD;AAErD,OAAO,EACL,+BAA+B,GAEhC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,iBAAiB,EACjB,iCAAiC,EACjC,wBAAwB,GAEzB,MAAM,mBAAmB,CAAC;AAY3B,MAAM,UAAU,eAAe,CAC7B,OAAyC;IAEzC,MAAM,EACJ,MAAM,EACN,QAAQ,EACR,KAAK,EACL,UAAU,EACV,SAAS,EACT,GAAG,aAAa,EACjB,GAAG,OAAO,CAAC;IACZ,MAAM,MAAM,GAAG,wBAAwB,CAAC;QACtC,MAAM;QACN,GAAG,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC;QAC/C,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACzC,GAAG,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,CAAC;QACnD,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;KAClD,CAAC,CAAC;IACH,OAAO,+BAA+B,CAAW;QAC/C,GAAG,aAAa;QAChB,aAAa,EAAE,YAAY,MAAM,CAAC,KAAK,EAAE;QACzC,0BAA0B,EAAE,iCAAiC;QAC7D,QAAQ,EAAE,iBAAiB,CAAC,MAAM,CAAC;KACpC,EAAE,IAAI,CAAC,CAAC;AACX,CAAC"}
|
package/examples/jev_router.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
// Jev Router — route with TypeSafe's Jev System One model instead of Dari's
|
|
2
|
-
// trained routing policy. Jev answers two typed questions per request (which candidate,
|
|
3
|
-
// how long a lease) and returns calibrated probabilities; the decision is
|
|
4
|
-
// built from those answers in this package.
|
|
5
|
-
//
|
|
6
|
-
// Requires TYPESAFE_API_KEY, OPENAI_API_KEY, and ANTHROPIC_API_KEY.
|
|
7
|
-
|
|
8
|
-
import { createJevRouter, createPiRuntime, createRouter } from "../src/index.js";
|
|
9
|
-
|
|
10
|
-
const pi = await createPiRuntime({
|
|
11
|
-
apiKey: ({ provider }) => {
|
|
12
|
-
const key = process.env[`${provider.toUpperCase()}_API_KEY`];
|
|
13
|
-
if (!key) throw new Error(`Missing ${provider.toUpperCase()}_API_KEY`);
|
|
14
|
-
return key;
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
const SOL = "openai/gpt-5.6-sol";
|
|
19
|
-
const SONNET = "anthropic/claude-sonnet-5";
|
|
20
|
-
|
|
21
|
-
const router = createRouter({
|
|
22
|
-
models: [pi.model(SOL), pi.model(SONNET)],
|
|
23
|
-
policy: createJevRouter({
|
|
24
|
-
apiKey: process.env.TYPESAFE_API_KEY!,
|
|
25
|
-
// Jev routes on cost evidence you supply; these are per-million-token USD
|
|
26
|
-
// prices and observed output-token averages for each enabled pair.
|
|
27
|
-
pricing: (model) => model === SOL
|
|
28
|
-
? { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 }
|
|
29
|
-
: { input: 3, output: 15, cacheRead: 0.3, cacheWrite: 3.75 },
|
|
30
|
-
averageOutputTokensByModel: {
|
|
31
|
-
[SOL]: { medium: 800 },
|
|
32
|
-
[SONNET]: { medium: 800 },
|
|
33
|
-
},
|
|
34
|
-
}),
|
|
35
|
-
executor: pi,
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const response = await router.fetch(
|
|
39
|
-
new Request("https://example.test/v1/chat/completions", {
|
|
40
|
-
method: "POST",
|
|
41
|
-
headers: { "Content-Type": "application/json" },
|
|
42
|
-
body: JSON.stringify({
|
|
43
|
-
model: "dari/routing",
|
|
44
|
-
messages: [{ role: "user", content: "Explain speculative decoding in one paragraph." }],
|
|
45
|
-
}),
|
|
46
|
-
}),
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
if (!response.ok) throw new Error(await response.text());
|
|
50
|
-
console.log(response.headers.get("X-Router-Selected-Model"), await response.json());
|