Download src/skynet/runtime-observer/trajectory-learner.ts from Darochin/openskynet: direct link, hf CLI and curl.
- Browser
- Download file 3.09 kB
-
https://huggingface.co/Darochin/openskynet/resolve/main/src/skynet/runtime-observer/trajectory-learner.ts
- Command line
-
hf download hf://Darochin/openskynet/src/skynet/runtime-observer/trajectory-learner.ts
-
curl -L -o trajectory-learner.ts https://huggingface.co/Darochin/openskynet/resolve/main/src/skynet/runtime-observer/trajectory-learner.ts
3.09 kB
| import type { SkynetCausalValenceLabel } from "../causal-valence/episode-ledger.js"; | |
| import { | |
| encodeSkynetRuntimeTrajectoryFeatures, | |
| type SkynetRuntimeTrajectorySample, | |
| } from "./trajectory-builder.js"; | |
| export type SkynetRuntimeObserverModel = { | |
| labels: SkynetCausalValenceLabel[]; | |
| centroids: Record<SkynetCausalValenceLabel, number[]>; | |
| counts: Record<SkynetCausalValenceLabel, number>; | |
| }; | |
| export type SkynetRuntimeObserverPrediction = { | |
| label: SkynetCausalValenceLabel; | |
| scores: Record<SkynetCausalValenceLabel, number>; | |
| }; | |
| const LABELS: SkynetCausalValenceLabel[] = ["progress", "relief", "stall", "frustration", "damage"]; | |
| function zeroVector(length: number): number[] { | |
| return Array.from({ length }, () => 0); | |
| } | |
| function cosineSimilarity(a: number[], b: number[]): number { | |
| let dot = 0; | |
| let normA = 0; | |
| let normB = 0; | |
| for (let index = 0; index < a.length; index += 1) { | |
| const av = a[index] ?? 0; | |
| const bv = b[index] ?? 0; | |
| dot += av * bv; | |
| normA += av * av; | |
| normB += bv * bv; | |
| } | |
| if (normA === 0 || normB === 0) { | |
| return 0; | |
| } | |
| return dot / (Math.sqrt(normA) * Math.sqrt(normB)); | |
| } | |
| export function trainSkynetRuntimeObserverModel( | |
| samples: SkynetRuntimeTrajectorySample[], | |
| ): SkynetRuntimeObserverModel | null { | |
| if (samples.length === 0) { | |
| return null; | |
| } | |
| const vectorLength = encodeSkynetRuntimeTrajectoryFeatures(samples[0]).length; | |
| const sums = LABELS.reduce( | |
| (acc, label) => { | |
| acc[label] = zeroVector(vectorLength); | |
| return acc; | |
| }, | |
| {} as Record<SkynetCausalValenceLabel, number[]>, | |
| ); | |
| const counts = LABELS.reduce( | |
| (acc, label) => { | |
| acc[label] = 0; | |
| return acc; | |
| }, | |
| {} as Record<SkynetCausalValenceLabel, number>, | |
| ); | |
| for (const sample of samples) { | |
| const vector = encodeSkynetRuntimeTrajectoryFeatures(sample); | |
| counts[sample.targetLabel] += 1; | |
| for (let index = 0; index < vector.length; index += 1) { | |
| sums[sample.targetLabel][index] += vector[index] ?? 0; | |
| } | |
| } | |
| const centroids = LABELS.reduce( | |
| (acc, label) => { | |
| const count = counts[label]; | |
| acc[label] = count > 0 ? sums[label].map((value) => value / count) : zeroVector(vectorLength); | |
| return acc; | |
| }, | |
| {} as Record<SkynetCausalValenceLabel, number[]>, | |
| ); | |
| return { | |
| labels: LABELS.filter((label) => counts[label] > 0), | |
| centroids, | |
| counts, | |
| }; | |
| } | |
| export function predictSkynetRuntimeObserverLabel( | |
| model: SkynetRuntimeObserverModel, | |
| sample: SkynetRuntimeTrajectorySample, | |
| ): SkynetRuntimeObserverPrediction { | |
| const vector = encodeSkynetRuntimeTrajectoryFeatures(sample); | |
| const scores = model.labels.reduce( | |
| (acc, label) => { | |
| acc[label] = cosineSimilarity(vector, model.centroids[label]); | |
| return acc; | |
| }, | |
| {} as Record<SkynetCausalValenceLabel, number>, | |
| ); | |
| const label = | |
| model.labels | |
| .slice() | |
| .sort( | |
| (left, right) => | |
| (scores[right] ?? Number.NEGATIVE_INFINITY) - (scores[left] ?? Number.NEGATIVE_INFINITY), | |
| ) | |
| .at(0) ?? "stall"; | |
| return { label, scores }; | |
| } | |