mirror of
https://github.com/Kaelio/ktx.git
synced 2026-07-19 11:41:02 +02:00
rename klo to ktx
This commit is contained in:
parent
1a42152e6f
commit
3ce510b55b
704 changed files with 10205 additions and 10255 deletions
|
|
@ -3,13 +3,13 @@ import { tmpdir } from 'node:os';
|
|||
import { join } from 'node:path';
|
||||
import { afterEach, describe, expect, it } from 'vitest';
|
||||
import {
|
||||
createJsonlKloLlmDebugRequestRecorder,
|
||||
summarizeKloLlmDebugRequest,
|
||||
createJsonlKtxLlmDebugRequestRecorder,
|
||||
summarizeKtxLlmDebugRequest,
|
||||
} from './debug-request-recorder.js';
|
||||
|
||||
describe('summarizeKloLlmDebugRequest', () => {
|
||||
describe('summarizeKtxLlmDebugRequest', () => {
|
||||
it('records providerOptions positions without message text or tool schemas', () => {
|
||||
const summary = summarizeKloLlmDebugRequest({
|
||||
const summary = summarizeKtxLlmDebugRequest({
|
||||
operationName: 'ingest-bundle-wu',
|
||||
source: 'metabase',
|
||||
jobId: 'job-1',
|
||||
|
|
@ -81,7 +81,7 @@ describe('summarizeKloLlmDebugRequest', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('createJsonlKloLlmDebugRequestRecorder', () => {
|
||||
describe('createJsonlKtxLlmDebugRequestRecorder', () => {
|
||||
let tempDir: string | undefined;
|
||||
|
||||
afterEach(async () => {
|
||||
|
|
@ -92,9 +92,9 @@ describe('createJsonlKloLlmDebugRequestRecorder', () => {
|
|||
});
|
||||
|
||||
it('appends one JSON object per recorded request', async () => {
|
||||
tempDir = await mkdtemp(join(tmpdir(), 'klo-llm-debug-'));
|
||||
tempDir = await mkdtemp(join(tmpdir(), 'ktx-llm-debug-'));
|
||||
const filePath = join(tempDir, 'nested', 'llm-debug.jsonl');
|
||||
const recorder = createJsonlKloLlmDebugRequestRecorder(filePath);
|
||||
const recorder = createJsonlKtxLlmDebugRequestRecorder(filePath);
|
||||
|
||||
await recorder.record({
|
||||
timestamp: '2026-05-04T00:00:00.000Z',
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { appendFile, mkdir } from 'node:fs/promises';
|
||||
import { dirname } from 'node:path';
|
||||
import type { ModelMessage } from 'ai';
|
||||
import type { KloModelRole } from '@klo/llm';
|
||||
import type { KtxModelRole } from '@ktx/llm';
|
||||
|
||||
type ProviderOptionsCarrier = { providerOptions?: unknown; [key: string]: unknown };
|
||||
type ToolMap = Record<string, ProviderOptionsCarrier>;
|
||||
|
||||
export interface KloLlmDebugProviderOptionsEntry {
|
||||
export interface KtxLlmDebugProviderOptionsEntry {
|
||||
target: 'message' | 'message-part' | 'tool';
|
||||
index?: number;
|
||||
role?: string;
|
||||
|
|
@ -15,29 +15,29 @@ export interface KloLlmDebugProviderOptionsEntry {
|
|||
providerOptions: unknown;
|
||||
}
|
||||
|
||||
export interface KloLlmDebugRequest {
|
||||
export interface KtxLlmDebugRequest {
|
||||
timestamp: string;
|
||||
operationName: string;
|
||||
source?: string;
|
||||
jobId?: string;
|
||||
unitKey?: string;
|
||||
modelRole: KloModelRole;
|
||||
modelRole: KtxModelRole;
|
||||
modelId: string;
|
||||
messageCount: number;
|
||||
toolNames: string[];
|
||||
providerOptions: KloLlmDebugProviderOptionsEntry[];
|
||||
providerOptions: KtxLlmDebugProviderOptionsEntry[];
|
||||
}
|
||||
|
||||
export interface KloLlmDebugRequestRecorder {
|
||||
record(request: KloLlmDebugRequest): Promise<void> | void;
|
||||
export interface KtxLlmDebugRequestRecorder {
|
||||
record(request: KtxLlmDebugRequest): Promise<void> | void;
|
||||
}
|
||||
|
||||
export interface SummarizeKloLlmDebugRequestInput {
|
||||
export interface SummarizeKtxLlmDebugRequestInput {
|
||||
operationName: string;
|
||||
source?: string;
|
||||
jobId?: string;
|
||||
unitKey?: string;
|
||||
modelRole: KloModelRole;
|
||||
modelRole: KtxModelRole;
|
||||
modelId: string;
|
||||
messages: ModelMessage[];
|
||||
tools: ToolMap;
|
||||
|
|
@ -52,7 +52,7 @@ function isProviderOptionsCarrier(value: unknown): value is ProviderOptionsCarri
|
|||
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
||||
}
|
||||
|
||||
function contentPartProviderOptions(message: ModelMessage, index: number): KloLlmDebugProviderOptionsEntry[] {
|
||||
function contentPartProviderOptions(message: ModelMessage, index: number): KtxLlmDebugProviderOptionsEntry[] {
|
||||
if (!Array.isArray(message.content)) {
|
||||
return [];
|
||||
}
|
||||
|
|
@ -74,9 +74,9 @@ function contentPartProviderOptions(message: ModelMessage, index: number): KloLl
|
|||
});
|
||||
}
|
||||
|
||||
function messageProviderOptions(messages: ModelMessage[]): KloLlmDebugProviderOptionsEntry[] {
|
||||
function messageProviderOptions(messages: ModelMessage[]): KtxLlmDebugProviderOptionsEntry[] {
|
||||
return messages.flatMap((message, index) => {
|
||||
const entries: KloLlmDebugProviderOptionsEntry[] = [];
|
||||
const entries: KtxLlmDebugProviderOptionsEntry[] = [];
|
||||
const providerOptions = (message as ProviderOptionsCarrier).providerOptions;
|
||||
if (providerOptions) {
|
||||
entries.push({
|
||||
|
|
@ -91,7 +91,7 @@ function messageProviderOptions(messages: ModelMessage[]): KloLlmDebugProviderOp
|
|||
});
|
||||
}
|
||||
|
||||
function toolProviderOptions(tools: ToolMap): KloLlmDebugProviderOptionsEntry[] {
|
||||
function toolProviderOptions(tools: ToolMap): KtxLlmDebugProviderOptionsEntry[] {
|
||||
return Object.entries(tools).flatMap(([name, tool]) => {
|
||||
return tool.providerOptions
|
||||
? [
|
||||
|
|
@ -105,7 +105,7 @@ function toolProviderOptions(tools: ToolMap): KloLlmDebugProviderOptionsEntry[]
|
|||
});
|
||||
}
|
||||
|
||||
export function summarizeKloLlmDebugRequest(input: SummarizeKloLlmDebugRequestInput): KloLlmDebugRequest {
|
||||
export function summarizeKtxLlmDebugRequest(input: SummarizeKtxLlmDebugRequestInput): KtxLlmDebugRequest {
|
||||
const toolNames = Object.keys(input.tools).sort();
|
||||
return {
|
||||
timestamp: input.timestamp ?? new Date().toISOString(),
|
||||
|
|
@ -121,7 +121,7 @@ export function summarizeKloLlmDebugRequest(input: SummarizeKloLlmDebugRequestIn
|
|||
};
|
||||
}
|
||||
|
||||
export function createJsonlKloLlmDebugRequestRecorder(filePath: string): KloLlmDebugRequestRecorder {
|
||||
export function createJsonlKtxLlmDebugRequestRecorder(filePath: string): KtxLlmDebugRequestRecorder {
|
||||
return {
|
||||
async record(request) {
|
||||
await mkdir(dirname(filePath), { recursive: true });
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { KloIngestEmbeddingPortAdapter, KloScanEmbeddingPortAdapter } from './embedding-port.js';
|
||||
import { KtxIngestEmbeddingPortAdapter, KtxScanEmbeddingPortAdapter } from './embedding-port.js';
|
||||
|
||||
describe('KLO embedding port adapters', () => {
|
||||
it('adapts @klo/llm embeddings to ingest embedding port shape', async () => {
|
||||
describe('KTX embedding port adapters', () => {
|
||||
it('adapts @ktx/llm embeddings to ingest embedding port shape', async () => {
|
||||
const provider = {
|
||||
dimensions: 3,
|
||||
maxBatchSize: 2,
|
||||
|
|
@ -12,7 +12,7 @@ describe('KLO embedding port adapters', () => {
|
|||
[4, 5, 6],
|
||||
]),
|
||||
};
|
||||
const adapter = new KloIngestEmbeddingPortAdapter(provider as never);
|
||||
const adapter = new KtxIngestEmbeddingPortAdapter(provider as never);
|
||||
|
||||
await expect(adapter.computeEmbedding('alpha')).resolves.toEqual([1, 2, 3]);
|
||||
await expect(adapter.computeEmbeddingsBulk(['alpha', 'beta'])).resolves.toEqual([
|
||||
|
|
@ -22,14 +22,14 @@ describe('KLO embedding port adapters', () => {
|
|||
expect(adapter.maxBatchSize).toBe(2);
|
||||
});
|
||||
|
||||
it('adapts @klo/llm embeddings to scan embedding port shape', async () => {
|
||||
it('adapts @ktx/llm embeddings to scan embedding port shape', async () => {
|
||||
const provider = {
|
||||
dimensions: 3,
|
||||
maxBatchSize: 2,
|
||||
embed: vi.fn(),
|
||||
[['embed', 'Many'].join('')]: vi.fn(async () => [[1, 2, 3]]),
|
||||
};
|
||||
const adapter = new KloScanEmbeddingPortAdapter(provider as never);
|
||||
const adapter = new KtxScanEmbeddingPortAdapter(provider as never);
|
||||
|
||||
await expect(adapter.embedBatch(['alpha'])).resolves.toEqual([[1, 2, 3]]);
|
||||
expect(adapter.dimensions).toBe(3);
|
||||
|
|
|
|||
|
|
@ -1,17 +1,17 @@
|
|||
import type { KloEmbeddingProvider } from '@klo/llm';
|
||||
import type { KloEmbeddingPort as KloIngestEmbeddingPort } from '../core/embedding.js';
|
||||
import type { KloEmbeddingPort as KloScanEmbeddingPort } from '../scan/types.js';
|
||||
import type { KtxEmbeddingProvider } from '@ktx/llm';
|
||||
import type { KtxEmbeddingPort as KtxIngestEmbeddingPort } from '../core/embedding.js';
|
||||
import type { KtxEmbeddingPort as KtxScanEmbeddingPort } from '../scan/types.js';
|
||||
|
||||
const bulkEmbeddingMethod = ['embed', 'Many'].join('') as keyof KloEmbeddingProvider;
|
||||
const bulkEmbeddingMethod = ['embed', 'Many'].join('') as keyof KtxEmbeddingProvider;
|
||||
|
||||
function computeBulkEmbeddings(provider: KloEmbeddingProvider, texts: string[]): Promise<number[][]> {
|
||||
function computeBulkEmbeddings(provider: KtxEmbeddingProvider, texts: string[]): Promise<number[][]> {
|
||||
return (provider[bulkEmbeddingMethod] as (items: string[]) => Promise<number[][]>)(texts);
|
||||
}
|
||||
|
||||
export class KloIngestEmbeddingPortAdapter implements KloIngestEmbeddingPort {
|
||||
export class KtxIngestEmbeddingPortAdapter implements KtxIngestEmbeddingPort {
|
||||
readonly maxBatchSize: number;
|
||||
|
||||
constructor(private readonly provider: KloEmbeddingProvider) {
|
||||
constructor(private readonly provider: KtxEmbeddingProvider) {
|
||||
this.maxBatchSize = provider.maxBatchSize;
|
||||
}
|
||||
|
||||
|
|
@ -24,11 +24,11 @@ export class KloIngestEmbeddingPortAdapter implements KloIngestEmbeddingPort {
|
|||
}
|
||||
}
|
||||
|
||||
export class KloScanEmbeddingPortAdapter implements KloScanEmbeddingPort {
|
||||
export class KtxScanEmbeddingPortAdapter implements KtxScanEmbeddingPort {
|
||||
readonly dimensions: number;
|
||||
readonly maxBatchSize: number;
|
||||
|
||||
constructor(private readonly provider: KloEmbeddingProvider) {
|
||||
constructor(private readonly provider: KtxEmbeddingProvider) {
|
||||
this.dimensions = provider.dimensions;
|
||||
this.maxBatchSize = provider.maxBatchSize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import { KloMessageBuilder, type KloLlmProvider, type KloModelRole } from '@klo/llm';
|
||||
import { KtxMessageBuilder, type KtxLlmProvider, type KtxModelRole } from '@ktx/llm';
|
||||
import { generateText, Output, type FlexibleSchema, type ToolSet } from 'ai';
|
||||
|
||||
type GenerateTextInput = Parameters<typeof generateText>[0];
|
||||
type GenerateTextFn = (input: GenerateTextInput) => Promise<{ text?: string; output?: unknown }>;
|
||||
|
||||
interface GenerateKloTextInput {
|
||||
llmProvider: KloLlmProvider;
|
||||
role: KloModelRole;
|
||||
interface GenerateKtxTextInput {
|
||||
llmProvider: KtxLlmProvider;
|
||||
role: KtxModelRole;
|
||||
prompt: string;
|
||||
system?: string;
|
||||
tools?: ToolSet;
|
||||
|
|
@ -14,12 +14,12 @@ interface GenerateKloTextInput {
|
|||
generateText?: GenerateTextFn;
|
||||
}
|
||||
|
||||
export async function generateKloText(input: GenerateKloTextInput): Promise<string> {
|
||||
export async function generateKtxText(input: GenerateKtxTextInput): Promise<string> {
|
||||
const model = input.llmProvider.getModel(input.role);
|
||||
if ((model as { provider?: string }).provider === 'deterministic') {
|
||||
return `Deterministic description for ${input.prompt.slice(0, 64).trim() || 'data source'}`;
|
||||
}
|
||||
const built = new KloMessageBuilder(input.llmProvider).wrapSimple({
|
||||
const built = new KtxMessageBuilder(input.llmProvider).wrapSimple({
|
||||
system: input.system,
|
||||
messages: [{ role: 'user', content: input.prompt }],
|
||||
tools: input.tools ?? {},
|
||||
|
|
@ -32,16 +32,16 @@ export async function generateKloText(input: GenerateKloTextInput): Promise<stri
|
|||
tools: built.tools as ToolSet,
|
||||
});
|
||||
if (typeof result.text !== 'string') {
|
||||
throw new Error('KLO LLM text generation returned no text');
|
||||
throw new Error('KTX LLM text generation returned no text');
|
||||
}
|
||||
return result.text;
|
||||
}
|
||||
|
||||
export async function generateKloObject<TOutput, TSchema>(
|
||||
input: GenerateKloTextInput & { schema: TSchema },
|
||||
export async function generateKtxObject<TOutput, TSchema>(
|
||||
input: GenerateKtxTextInput & { schema: TSchema },
|
||||
): Promise<TOutput> {
|
||||
const model = input.llmProvider.getModel(input.role);
|
||||
const built = new KloMessageBuilder(input.llmProvider).wrapSimple({
|
||||
const built = new KtxMessageBuilder(input.llmProvider).wrapSimple({
|
||||
system: input.system,
|
||||
messages: [{ role: 'user', content: input.prompt }],
|
||||
tools: input.tools ?? {},
|
||||
|
|
@ -57,7 +57,7 @@ export async function generateKloObject<TOutput, TSchema>(
|
|||
}),
|
||||
});
|
||||
if (result.output == null) {
|
||||
throw new Error('KLO LLM object generation returned no output');
|
||||
throw new Error('KTX LLM object generation returned no output');
|
||||
}
|
||||
return result.output as TOutput;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
export { KloIngestEmbeddingPortAdapter, KloScanEmbeddingPortAdapter } from './embedding-port.js';
|
||||
export { generateKloObject, generateKloText } from './generation.js';
|
||||
export { KtxIngestEmbeddingPortAdapter, KtxScanEmbeddingPortAdapter } from './embedding-port.js';
|
||||
export { generateKtxObject, generateKtxText } from './generation.js';
|
||||
export type {
|
||||
KloLlmDebugProviderOptionsEntry,
|
||||
KloLlmDebugRequest,
|
||||
KloLlmDebugRequestRecorder,
|
||||
SummarizeKloLlmDebugRequestInput,
|
||||
KtxLlmDebugProviderOptionsEntry,
|
||||
KtxLlmDebugRequest,
|
||||
KtxLlmDebugRequestRecorder,
|
||||
SummarizeKtxLlmDebugRequestInput,
|
||||
} from './debug-request-recorder.js';
|
||||
export {
|
||||
createJsonlKloLlmDebugRequestRecorder,
|
||||
summarizeKloLlmDebugRequest,
|
||||
createJsonlKtxLlmDebugRequestRecorder,
|
||||
summarizeKtxLlmDebugRequest,
|
||||
} from './debug-request-recorder.js';
|
||||
export {
|
||||
createLocalKloEmbeddingProviderFromConfig,
|
||||
createLocalKloLlmProviderFromConfig,
|
||||
resolveLocalKloEmbeddingConfig,
|
||||
resolveLocalKloLlmConfig,
|
||||
createLocalKtxEmbeddingProviderFromConfig,
|
||||
createLocalKtxLlmProviderFromConfig,
|
||||
resolveLocalKtxEmbeddingConfig,
|
||||
resolveLocalKtxLlmConfig,
|
||||
} from './local-config.js';
|
||||
|
|
|
|||
|
|
@ -1,31 +1,31 @@
|
|||
import { describe, expect, it, vi } from 'vitest';
|
||||
import {
|
||||
buildDefaultKloProjectConfig,
|
||||
type KloProjectEmbeddingConfig,
|
||||
type KloProjectLlmConfig,
|
||||
buildDefaultKtxProjectConfig,
|
||||
type KtxProjectEmbeddingConfig,
|
||||
type KtxProjectLlmConfig,
|
||||
} from '../project/config.js';
|
||||
import {
|
||||
createLocalKloEmbeddingProviderFromConfig,
|
||||
createLocalKloLlmProviderFromConfig,
|
||||
resolveLocalKloEmbeddingConfig,
|
||||
resolveLocalKloLlmConfig,
|
||||
createLocalKtxEmbeddingProviderFromConfig,
|
||||
createLocalKtxLlmProviderFromConfig,
|
||||
resolveLocalKtxEmbeddingConfig,
|
||||
resolveLocalKtxLlmConfig,
|
||||
} from './local-config.js';
|
||||
|
||||
describe('local KLO LLM config', () => {
|
||||
it('resolves env and file references into a KloLlmConfig', () => {
|
||||
const config: KloProjectLlmConfig = {
|
||||
describe('local KTX LLM config', () => {
|
||||
it('resolves env and file references into a KtxLlmConfig', () => {
|
||||
const config: KtxProjectLlmConfig = {
|
||||
provider: {
|
||||
backend: 'gateway',
|
||||
gateway: { api_key: 'env:AI_GATEWAY_API_KEY', base_url: 'https://gateway.example/v1' }, // pragma: allowlist secret
|
||||
},
|
||||
models: { default: 'env:KLO_MODEL', triage: 'anthropic/claude-haiku-4-5' },
|
||||
models: { default: 'env:KTX_MODEL', triage: 'anthropic/claude-haiku-4-5' },
|
||||
promptCaching: { enabled: false },
|
||||
};
|
||||
|
||||
expect(
|
||||
resolveLocalKloLlmConfig(config, {
|
||||
resolveLocalKtxLlmConfig(config, {
|
||||
AI_GATEWAY_API_KEY: 'gateway-key', // pragma: allowlist secret
|
||||
KLO_MODEL: 'anthropic/claude-sonnet-4-6',
|
||||
KTX_MODEL: 'anthropic/claude-sonnet-4-6',
|
||||
}),
|
||||
).toEqual({
|
||||
backend: 'gateway',
|
||||
|
|
@ -37,16 +37,16 @@ describe('local KLO LLM config', () => {
|
|||
|
||||
it('returns null when the local LLM backend is disabled', () => {
|
||||
expect(
|
||||
createLocalKloLlmProviderFromConfig({
|
||||
createLocalKtxLlmProviderFromConfig({
|
||||
provider: { backend: 'none' },
|
||||
models: {},
|
||||
}),
|
||||
).toBeNull();
|
||||
});
|
||||
|
||||
it('constructs providers through @klo/llm', () => {
|
||||
const createKloLlmProvider = vi.fn(() => ({ getModel: vi.fn() }) as never);
|
||||
const result = createLocalKloLlmProviderFromConfig(
|
||||
it('constructs providers through @ktx/llm', () => {
|
||||
const createKtxLlmProvider = vi.fn(() => ({ getModel: vi.fn() }) as never);
|
||||
const result = createLocalKtxLlmProviderFromConfig(
|
||||
{
|
||||
provider: {
|
||||
backend: 'anthropic',
|
||||
|
|
@ -54,11 +54,11 @@ describe('local KLO LLM config', () => {
|
|||
},
|
||||
models: { default: 'claude-sonnet-4-6' },
|
||||
},
|
||||
{ env: { ANTHROPIC_API_KEY: 'sk-ant-test' }, createKloLlmProvider }, // pragma: allowlist secret
|
||||
{ env: { ANTHROPIC_API_KEY: 'sk-ant-test' }, createKtxLlmProvider }, // pragma: allowlist secret
|
||||
);
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(createKloLlmProvider).toHaveBeenCalledWith({
|
||||
expect(createKtxLlmProvider).toHaveBeenCalledWith({
|
||||
backend: 'anthropic',
|
||||
anthropic: { apiKey: 'sk-ant-test' }, // pragma: allowlist secret
|
||||
modelSlots: { default: 'claude-sonnet-4-6' },
|
||||
|
|
@ -66,8 +66,8 @@ describe('local KLO LLM config', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('inherits enabled prompt caching from @klo/llm when local config omits promptCaching', () => {
|
||||
const provider = createLocalKloLlmProviderFromConfig({
|
||||
it('inherits enabled prompt caching from @ktx/llm when local config omits promptCaching', () => {
|
||||
const provider = createLocalKtxLlmProviderFromConfig({
|
||||
provider: {
|
||||
backend: 'gateway',
|
||||
gateway: { base_url: 'https://gateway.example/v1' },
|
||||
|
|
@ -85,9 +85,9 @@ describe('local KLO LLM config', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('local KLO embedding config', () => {
|
||||
describe('local KTX embedding config', () => {
|
||||
it('resolves sentence-transformers config', () => {
|
||||
const config: KloProjectEmbeddingConfig = {
|
||||
const config: KtxProjectEmbeddingConfig = {
|
||||
backend: 'sentence-transformers',
|
||||
model: 'all-MiniLM-L6-v2',
|
||||
dimensions: 384,
|
||||
|
|
@ -95,7 +95,7 @@ describe('local KLO embedding config', () => {
|
|||
batchSize: 16,
|
||||
};
|
||||
|
||||
expect(resolveLocalKloEmbeddingConfig(config, {})).toEqual({
|
||||
expect(resolveLocalKtxEmbeddingConfig(config, {})).toEqual({
|
||||
backend: 'sentence-transformers',
|
||||
model: 'all-MiniLM-L6-v2',
|
||||
dimensions: 384,
|
||||
|
|
@ -105,14 +105,14 @@ describe('local KLO embedding config', () => {
|
|||
});
|
||||
|
||||
it('constructs deterministic embeddings from the default project config', () => {
|
||||
const createKloEmbeddingProvider = vi.fn(() => ({}) as never);
|
||||
const provider = createLocalKloEmbeddingProviderFromConfig(
|
||||
buildDefaultKloProjectConfig('warehouse').ingest.embeddings,
|
||||
{ createKloEmbeddingProvider },
|
||||
const createKtxEmbeddingProvider = vi.fn(() => ({}) as never);
|
||||
const provider = createLocalKtxEmbeddingProviderFromConfig(
|
||||
buildDefaultKtxProjectConfig('warehouse').ingest.embeddings,
|
||||
{ createKtxEmbeddingProvider },
|
||||
);
|
||||
|
||||
expect(provider).not.toBeNull();
|
||||
expect(createKloEmbeddingProvider).toHaveBeenCalledWith(
|
||||
expect(createKtxEmbeddingProvider).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
backend: 'deterministic',
|
||||
model: 'deterministic',
|
||||
|
|
@ -122,6 +122,6 @@ describe('local KLO embedding config', () => {
|
|||
});
|
||||
|
||||
it('returns null when embeddings are disabled', () => {
|
||||
expect(createLocalKloEmbeddingProviderFromConfig({ backend: 'none', dimensions: 8 })).toBeNull();
|
||||
expect(createLocalKtxEmbeddingProviderFromConfig({ backend: 'none', dimensions: 8 })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
import {
|
||||
createKloEmbeddingProvider,
|
||||
createKloLlmProvider,
|
||||
type KloEmbeddingConfig,
|
||||
type KloEmbeddingProvider,
|
||||
type KloLlmConfig,
|
||||
type KloLlmProvider,
|
||||
type KloModelRole,
|
||||
} from '@klo/llm';
|
||||
import { resolveKloConfigReference } from '../core/config-reference.js';
|
||||
import type { KloProjectEmbeddingConfig, KloProjectLlmConfig } from '../project/config.js';
|
||||
createKtxEmbeddingProvider,
|
||||
createKtxLlmProvider,
|
||||
type KtxEmbeddingConfig,
|
||||
type KtxEmbeddingProvider,
|
||||
type KtxLlmConfig,
|
||||
type KtxLlmProvider,
|
||||
type KtxModelRole,
|
||||
} from '@ktx/llm';
|
||||
import { resolveKtxConfigReference } from '../core/config-reference.js';
|
||||
import type { KtxProjectEmbeddingConfig, KtxProjectLlmConfig } from '../project/config.js';
|
||||
|
||||
interface LocalConfigDeps {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
createKloLlmProvider?: typeof createKloLlmProvider;
|
||||
createKloEmbeddingProvider?: typeof createKloEmbeddingProvider;
|
||||
createKtxLlmProvider?: typeof createKtxLlmProvider;
|
||||
createKtxEmbeddingProvider?: typeof createKtxEmbeddingProvider;
|
||||
}
|
||||
|
||||
function resolveOptional(value: string | undefined, env: NodeJS.ProcessEnv): string | undefined {
|
||||
return resolveKloConfigReference(value, env) || undefined;
|
||||
return resolveKtxConfigReference(value, env) || undefined;
|
||||
}
|
||||
|
||||
function resolveRequired(value: string | undefined, env: NodeJS.ProcessEnv, message: string): string {
|
||||
|
|
@ -29,19 +29,19 @@ function resolveRequired(value: string | undefined, env: NodeJS.ProcessEnv, mess
|
|||
}
|
||||
|
||||
function resolveModelSlots(
|
||||
models: KloProjectLlmConfig['models'],
|
||||
models: KtxProjectLlmConfig['models'],
|
||||
env: NodeJS.ProcessEnv,
|
||||
): KloLlmConfig['modelSlots'] {
|
||||
const resolved: Partial<Record<KloModelRole, string>> & { default?: string } = {};
|
||||
): KtxLlmConfig['modelSlots'] {
|
||||
const resolved: Partial<Record<KtxModelRole, string>> & { default?: string } = {};
|
||||
for (const [role, value] of Object.entries(models)) {
|
||||
if (value) {
|
||||
resolved[role as KloModelRole] = resolveRequired(value, env, `llm.models.${role} is required`);
|
||||
resolved[role as KtxModelRole] = resolveRequired(value, env, `llm.models.${role} is required`);
|
||||
}
|
||||
}
|
||||
if (!resolved.default) {
|
||||
throw new Error('llm.models.default is required when llm.provider.backend is not none');
|
||||
}
|
||||
return resolved as KloLlmConfig['modelSlots'];
|
||||
return resolved as KtxLlmConfig['modelSlots'];
|
||||
}
|
||||
|
||||
function resolvedProviderConfig(
|
||||
|
|
@ -64,7 +64,7 @@ function resolvedProviderConfig(
|
|||
};
|
||||
}
|
||||
|
||||
export function resolveLocalKloLlmConfig(config: KloProjectLlmConfig, env: NodeJS.ProcessEnv): KloLlmConfig | null {
|
||||
export function resolveLocalKtxLlmConfig(config: KtxProjectLlmConfig, env: NodeJS.ProcessEnv): KtxLlmConfig | null {
|
||||
if (config.provider.backend === 'none') {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -81,18 +81,18 @@ export function resolveLocalKloLlmConfig(config: KloProjectLlmConfig, env: NodeJ
|
|||
};
|
||||
}
|
||||
|
||||
export function createLocalKloLlmProviderFromConfig(
|
||||
config: KloProjectLlmConfig,
|
||||
export function createLocalKtxLlmProviderFromConfig(
|
||||
config: KtxProjectLlmConfig,
|
||||
deps: LocalConfigDeps = {},
|
||||
): KloLlmProvider | null {
|
||||
const resolved = resolveLocalKloLlmConfig(config, deps.env ?? process.env);
|
||||
return resolved ? (deps.createKloLlmProvider ?? createKloLlmProvider)(resolved) : null;
|
||||
): KtxLlmProvider | null {
|
||||
const resolved = resolveLocalKtxLlmConfig(config, deps.env ?? process.env);
|
||||
return resolved ? (deps.createKtxLlmProvider ?? createKtxLlmProvider)(resolved) : null;
|
||||
}
|
||||
|
||||
export function resolveLocalKloEmbeddingConfig(
|
||||
config: KloProjectEmbeddingConfig,
|
||||
export function resolveLocalKtxEmbeddingConfig(
|
||||
config: KtxProjectEmbeddingConfig,
|
||||
env: NodeJS.ProcessEnv,
|
||||
): KloEmbeddingConfig | null {
|
||||
): KtxEmbeddingConfig | null {
|
||||
if (config.backend === 'none') {
|
||||
return null;
|
||||
}
|
||||
|
|
@ -113,10 +113,10 @@ export function resolveLocalKloEmbeddingConfig(
|
|||
};
|
||||
}
|
||||
|
||||
export function createLocalKloEmbeddingProviderFromConfig(
|
||||
config: KloProjectEmbeddingConfig,
|
||||
export function createLocalKtxEmbeddingProviderFromConfig(
|
||||
config: KtxProjectEmbeddingConfig,
|
||||
deps: LocalConfigDeps = {},
|
||||
): KloEmbeddingProvider | null {
|
||||
const resolved = resolveLocalKloEmbeddingConfig(config, deps.env ?? process.env);
|
||||
return resolved ? (deps.createKloEmbeddingProvider ?? createKloEmbeddingProvider)(resolved) : null;
|
||||
): KtxEmbeddingProvider | null {
|
||||
const resolved = resolveLocalKtxEmbeddingConfig(config, deps.env ?? process.env);
|
||||
return resolved ? (deps.createKtxEmbeddingProvider ?? createKtxEmbeddingProvider)(resolved) : null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue