@maximai/maxim-js
Version:
Maxim AI JS SDK. Visit https://getmaxim.ai for more info.
418 lines • 15.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.EvaluateContainer = exports.EventEmittingBaseContainer = exports.EvaluatableBaseContainer = exports.BaseContainer = void 0;
const uuid_1 = require("uuid");
const utils_1 = require("../utils");
const types_1 = require("./types");
/**
* Abstract base class for all logging containers in the Maxim SDK.
*
* Provides common functionality for managing container lifecycle, metadata, tags,
* and communication with the log writer. All specific container types extend this class.
*
* @abstract
* @class BaseContainer
* @example
* // BaseContainer is not instantiated directly, but through subclasses
* const session = new Session({ id: 'session-1', name: 'User Chat' }, writer);
* session.addTag('user_id', '12345');
* session.addMetadata({ context: 'support_chat' });
*/
class BaseContainer {
/**
* Creates a new base container instance.
*
* @param entity - The entity type this container represents
* @param config - Configuration for the container
* @param writer - Log writer instance for committing changes
* @throws {Error} When the provided ID contains invalid characters (only alphanumeric, hyphens, and underscores allowed; only throws if you have `raiseExceptions` config set to true)
*/
constructor(entity, config, writer) {
var _a;
this.entity = entity;
if (!config.id) {
config.id = (0, utils_1.uniqueId)();
}
// Validate ID format - only allow alphanumeric characters, hyphens, and underscores
if (!/^[a-zA-Z0-9_-]+$/.test(config.id)) {
if (writer.raiseExceptions) {
throw new Error(`Invalid ID: ${config.id}. ID must only contain alphanumeric characters, hyphens, and underscores. Event will not be logged.`);
}
else {
console.error(`Invalid ID: ${config.id}. ID must only contain alphanumeric characters, hyphens, and underscores. Event will not be logged.`);
this._id = (0, uuid_1.v4)();
}
}
else {
this._id = config.id;
}
this._name = config.name;
this.spanId = config.spanId;
// Use provided startTimestamp if available, otherwise default to current time
this.startTimestamp = (_a = config.startTimestamp) !== null && _a !== void 0 ? _a : new Date();
// Use provided endTimestamp if available
this.endTimestamp = config.endTimestamp;
this.tags = config.tags || {};
this.writer = writer;
}
/**
* Gets the unique identifier for this container.
*
* @returns The container's unique ID
*/
get id() {
return this._id;
}
/**
* Adds a tag to this container for categorization and filtering.
*
* @param key - The tag key
* @param value - The tag value
* @returns void
* @example
* container.addTag('environment', 'production');
* container.addTag('user_type', 'premium');
*/
addTag(key, value) {
this.commit("update", { tags: { [key]: value } });
}
/**
* Static method to add a tag to any container by ID.
*
* @param writer - The log writer instance
* @param entity - The entity type
* @param id - The container ID
* @param key - The tag key
* @param value - The tag value
* @returns void
*/
static addTag_(writer, entity, id, key, value) {
BaseContainer.commit_(writer, entity, id, "update", { tags: { [key]: value } });
}
/**
* Adds metadata to this container for additional context and debugging. Any data type could be added as the value in the metadata record.
*
* @param metadata - Key-value pairs of metadata
* @returns void
* @example
* container.addMetadata({
* requestId: 'req-123',
* userAgent: 'Mozilla/5.0...',
* processingTime: 1500
* });
*/
addMetadata(metadata) {
const sanitizedMetadata = Object.entries(metadata).reduce((acc, [key, value]) => {
acc[key] = (0, utils_1.serializeMetadataValue)(value);
return acc;
}, {});
this.commit("update", { metadata: sanitizedMetadata });
}
/**
* Static method to add metadata to any container by ID.
*
* @param writer - The log writer instance
* @param entity - The entity type
* @param id - The container ID
* @param metadata - The metadata to add
* @returns void
*/
static addMetadata_(writer, entity, id, metadata) {
const sanitizedMetadata = Object.entries(metadata).reduce((acc, [key, value]) => {
acc[key] = (0, utils_1.serializeMetadataValue)(value);
return acc;
}, {});
BaseContainer.commit_(writer, entity, id, "update", { metadata: sanitizedMetadata });
}
/**
* Marks this container as ended and records the end timestamp.
*
* @param endTimestamp - Optional explicit end timestamp. If not provided, defaults to current time.
* @returns void
* @example
* // End a container when processing is complete
* container.end();
*
* @example
* // End with explicit timestamp
* container.end(new Date('2024-01-15T10:30:00Z'));
*/
end(endTimestamp) {
this.endTimestamp = endTimestamp !== null && endTimestamp !== void 0 ? endTimestamp : new Date();
this.commit("end", { endTimestamp: this.endTimestamp });
}
/**
* Static method to end any container by ID.
*
* @param writer - The log writer instance
* @param entity - The entity type
* @param id - The container ID
* @param data - Optional additional data to include with the end event
* @returns void
*/
static end_(writer, entity, id, data) {
if (!data) {
data = { endTimestamp: new Date() };
}
else if (!data.endTimestamp) {
data.endTimestamp = new Date();
}
BaseContainer.commit_(writer, entity, id, "end", data);
}
/**
* Returns the current data state of this container.
*
* @returns The container's data.
*/
data() {
return {
name: this._name,
spanId: this.spanId,
tags: this.tags,
startTimestamp: this.startTimestamp,
endTimestamp: this.endTimestamp,
};
}
/**
* Commits a change to this container via the log writer.
*
* @protected
* @param action - The action being performed
* @param data - Data associated with the action
* @returns void
*/
commit(action, data) {
this.writer.commit(new types_1.CommitLog(this.entity, this._id, action, data ? data : this.data()));
}
/**
* Static method to commit changes to any container by ID.
*
* @protected
* @param writer - The log writer instance
* @param entity - The entity type
* @param id - The container ID
* @param action - The action being performed
* @param data - Data associated with the action
* @returns void
*/
static commit_(writer, entity, id, action, data) {
writer.commit(new types_1.CommitLog(entity, id, action, data !== null && data !== void 0 ? data : {}));
}
}
exports.BaseContainer = BaseContainer;
/**
* Extended base container that supports evaluation functionality.
*
* Provides additional capabilities for containers that can be evaluated,
* such as sessions, traces, generations, and retrievals. Includes methods
* for triggering evaluations.
*
* @abstract
* @class EvaluatableBaseContainer
* @extends BaseContainer
*/
class EvaluatableBaseContainer extends BaseContainer {
/**
* Gets the evaluation methods for this container.
*
* @returns Evaluation methods for configuring and triggering evaluations
* @example
* container.evaluate.withEvaluators('bias', 'toxicity');
*/
get evaluate() {
return new EvaluateContainer(this.writer, this.entity, this.id);
}
/**
* Static method to get evaluation methods for any evaluatable container by ID.
*
* @param writer - The log writer instance
* @param entity - The entity type
* @param id - The container ID
* @returns Evaluation methods for configuring and triggering evaluations
*/
static evaluate_(writer, entity, id) {
return new EvaluateContainer(writer, entity, id);
}
}
exports.EvaluatableBaseContainer = EvaluatableBaseContainer;
/**
* Extended evaluatable container that supports event emission.
*
* Provides capabilities for containers that can emit events. Used by traces and spans.
*
* @abstract
* @class EventEmittingBaseContainer
* @extends EvaluatableBaseContainer
*/
class EventEmittingBaseContainer extends EvaluatableBaseContainer {
/**
* Emits a custom event within this container.
*
* @param id - Unique identifier for the event
* @param name - Human-readable name for the event
* @param tags - Optional tags for categorizing the event
* @param metadata - Optional metadata for additional context
* @returns void
* @example
* container.event(
* 'checkpoint-1',
* 'Processing Milestone',
* { phase: 'preprocessing', status: 'complete' },
* { itemsProcessed: 1000, timeElapsed: 5.2 }
* );
*/
event(id, name, tags, metadata) {
if (metadata) {
const sanitizedMetadata = Object.entries(metadata).reduce((acc, [key, value]) => {
acc[key] = (0, utils_1.serializeMetadataValue)(value);
return acc;
}, {});
this.commit("add-event", { id: id, name, timestamp: new Date(), tags, metadata: sanitizedMetadata });
return;
}
this.commit("add-event", { id: id, name, timestamp: new Date(), tags });
}
/**
* Static method to emit an event for any event-emitting container by ID.
*
* @param writer - The log writer instance
* @param entity - The entity type
* @param id - The container ID
* @param eventId - Unique identifier for the event
* @param name - Human-readable name for the event
* @param tags - Optional tags for categorizing the event
* @param metadata - Optional metadata for additional context
* @returns void
*/
static event_(writer, entity, id, eventId, name, tags, metadata) {
if (metadata) {
const sanitizedMetadata = Object.entries(metadata).reduce((acc, [key, value]) => {
acc[key] = (0, utils_1.serializeMetadataValue)(value);
return acc;
}, {});
BaseContainer.commit_(writer, entity, id, "add-event", {
id: eventId,
name,
timestamp: new Date(),
tags,
metadata: sanitizedMetadata,
});
return;
}
BaseContainer.commit_(writer, entity, id, "add-event", { id: eventId, name, timestamp: new Date(), tags });
}
}
exports.EventEmittingBaseContainer = EventEmittingBaseContainer;
/**
* Container for configuring and triggering evaluations on containers.
*
* Provides an interface for setting up evaluations with variables.
* Used to assess the quality and performance of different operations
* for your application.
*
* @class EvaluateContainer
* @example
// Attaching evaluators to a container
* container.evaluate
* .withEvaluators('bias', 'toxicity')
* // Optionally, directly chain variables for the evaluators mentioned above
* .withVariables({ context: 'user_query', expected: 'gold_standard' });
*
* @example
* // Attaching variables at a later stage to specific evaluators
* container.evaluate
* .withVariables({ context: 'user_query', expected: 'gold_standard' }, ['bias']);
*/
class EvaluateContainer {
/**
* Creates a new evaluation container instance.
*
* @param writer - The log writer instance for committing evaluations
* @param entity - The entity type being evaluated
* @param id - The unique identifier of the entity being evaluated
* @example
* // Usually created through container.evaluate getter
* const evaluator = new EvaluateContainer(writer, Entity.GENERATION, 'gen-123');
*/
constructor(writer, entity, id) {
this._writer = writer;
this._entity = entity;
this._id = id;
}
/**
* Configures variables for specific evaluators in the evaluation.
*
* Variables provide the values needed by the evaluators to
* execute; such as expected outputs, retrieved contexts, or input queries.
*
* @template T - String literal type for variable names
* @param variables - Key-value pairs mapping variables to their values
* @param forEvaluators - Array of evaluator names that should receive these variables
* @example
* // Provide expected output for `accuracy` evaluator
* container.evaluate
* .withVariables(
* { expected_output: 'The correct answer is 42' },
* ['bias']
* )
*
* @example
* // Multiple variables for different evaluators
* container.evaluate
* .withVariables(
* { context: 'Retrieved documents...', user_query: 'What is AI?' },
* ['bias', 'toxicity']
* );
*/
withVariables(variables, forEvaluators) {
if (forEvaluators.length === 0)
return;
this._writer.commit(new types_1.CommitLog(this._entity, this._id, "evaluate", {
with: "variables",
variables,
evaluators: Array.from(new Set(forEvaluators)),
timestamp: new Date(),
}));
}
/**
* Specifies which evaluators should be attached for evaluation to this container.
*
* @template T - String literal type for evaluator names
* @param evaluators - Names of evaluators to be used for evaluation once all variables are available to them
* @example
* // Use built-in evaluators
* container.evaluate
* .withEvaluators('bias', 'toxicity');
*
* @example
* // Mix of built-in and custom evaluators
* container.evaluate
* .withEvaluators(
* 'bias',
* 'custom_domain_knowledge',
* 'brand_compliance'
* );
*/
withEvaluators(...evaluators) {
if (evaluators.length === 0) {
return {
withVariables: (variables) => {
this.withVariables(variables, evaluators);
},
};
}
const uniqueEvaluators = Array.from(new Set(evaluators));
this._writer.commit(new types_1.CommitLog(this._entity, this._id, "evaluate", {
with: "evaluators",
evaluators: uniqueEvaluators,
timestamp: new Date(),
}));
return {
withVariables: (variables) => {
this.withVariables(variables, uniqueEvaluators);
},
};
}
}
exports.EvaluateContainer = EvaluateContainer;
//# sourceMappingURL=base.js.map