npm package distribtion
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
|
||||||
@@ -1,8 +1,3 @@
|
|||||||
<p align="center">
|
|
||||||
<img src="./assets/logo.svg" width="600">
|
|
||||||
</p>
|
|
||||||
<br>
|
|
||||||
|
|
||||||
# JLINC Langchain Tracer
|
# JLINC Langchain Tracer
|
||||||
|
|
||||||
The JLINC Langchain Tracer is the official way to implement the zero-knowledge third-party auditing provided by the [JLINC Server](https://gitea.jlinc.io/jlinc-labs/jlinc-server) inside any Langchain-based infrastructure.
|
The JLINC Langchain Tracer is the official way to implement the zero-knowledge third-party auditing provided by the [JLINC Server](https://gitea.jlinc.io/jlinc-labs/jlinc-server) inside any Langchain-based infrastructure.
|
||||||
|
|||||||
127
dist/tracer.d.ts
vendored
Normal file
127
dist/tracer.d.ts
vendored
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
export type JLINCTracerFields = {
|
||||||
|
dataStoreApiUrl?: string | undefined;
|
||||||
|
dataStoreApiKey?: string | undefined;
|
||||||
|
archiveApiUrl?: string | undefined;
|
||||||
|
archiveApiKey?: string | undefined;
|
||||||
|
systemPrefix?: string | undefined;
|
||||||
|
agreementId?: string | null | undefined;
|
||||||
|
debug?: boolean | undefined;
|
||||||
|
};
|
||||||
|
export type SerializedRun = {
|
||||||
|
name?: string | undefined;
|
||||||
|
start_time?: number | undefined;
|
||||||
|
end_time?: number | undefined;
|
||||||
|
trace_id?: string | undefined;
|
||||||
|
inputs?: any;
|
||||||
|
outputs?: any;
|
||||||
|
extra?: {
|
||||||
|
metadata?: {
|
||||||
|
ls_provider?: string;
|
||||||
|
ls_model_name?: string;
|
||||||
|
};
|
||||||
|
} | undefined;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* @typedef {Object} JLINCTracerFields
|
||||||
|
* @property {string} [dataStoreApiUrl]
|
||||||
|
* @property {string} [dataStoreApiKey]
|
||||||
|
* @property {string} [archiveApiUrl]
|
||||||
|
* @property {string} [archiveApiKey]
|
||||||
|
* @property {string} [systemPrefix]
|
||||||
|
* @property {string|null} [agreementId]
|
||||||
|
* @property {boolean} [debug]
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @typedef {Object} SerializedRun
|
||||||
|
* @property {string} [name]
|
||||||
|
* @property {number} [start_time]
|
||||||
|
* @property {number} [end_time]
|
||||||
|
* @property {string} [trace_id]
|
||||||
|
* @property {any} [inputs]
|
||||||
|
* @property {any} [outputs]
|
||||||
|
* @property {{ metadata?: { ls_provider?: string, ls_model_name?: string } }} [extra]
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @extends {LangChainTracer}
|
||||||
|
*/
|
||||||
|
export class JLINCTracer extends LangChainTracer {
|
||||||
|
/**
|
||||||
|
* @param {JLINCTracerFields} [fields={}]
|
||||||
|
*/
|
||||||
|
constructor(fields?: JLINCTracerFields);
|
||||||
|
/** @type {string} */
|
||||||
|
dataStoreApiUrl: string;
|
||||||
|
/** @type {string} */
|
||||||
|
dataStoreApiKey: string;
|
||||||
|
/** @type {string} */
|
||||||
|
archiveApiUrl: string;
|
||||||
|
/** @type {string} */
|
||||||
|
archiveApiKey: string;
|
||||||
|
/** @type {string} */
|
||||||
|
systemPrefix: string;
|
||||||
|
/** @type {string|null} */
|
||||||
|
agreementId: string | null;
|
||||||
|
/** @type {boolean} */
|
||||||
|
debug: boolean;
|
||||||
|
/** @type {string|null} */
|
||||||
|
domain: string | null;
|
||||||
|
/** @type {Set<string>} */
|
||||||
|
entities: Set<string>;
|
||||||
|
/**
|
||||||
|
* @param {any} run
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
onRunCreate(run: any): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @param {any} run
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
onRunUpdate(run: any): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
getDefaultProjectName(): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
onLLMStart(serialized: SerializedRun): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
onLLMEnd(serialized: SerializedRun): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
onToolStart(serialized: SerializedRun): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
onToolEnd(serialized: SerializedRun): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @param {string} dir
|
||||||
|
* @param {any} payload
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
_postToApi(dir: string, payload: any): Promise<any>;
|
||||||
|
/**
|
||||||
|
* @param {string} entityShortName
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
_setEntity(entityShortName: string): Promise<void>;
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
_sanitize(input: string): string;
|
||||||
|
/**
|
||||||
|
* @param {any} payload
|
||||||
|
* @param {'in' | 'out'} direction
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
_jlincTrace(payload: any, direction: "in" | "out"): Promise<void>;
|
||||||
|
}
|
||||||
|
import { LangChainTracer } from "@langchain/core/dist/tracers/tracer_langchain";
|
||||||
241
dist/tracer.js
vendored
Normal file
241
dist/tracer.js
vendored
Normal file
@@ -0,0 +1,241 @@
|
|||||||
|
const { LangChainTracer } = require("@langchain/core/tracers/tracer_langchain");
|
||||||
|
const axios = require("axios");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} JLINCTracerFields
|
||||||
|
* @property {string} [dataStoreApiUrl]
|
||||||
|
* @property {string} [dataStoreApiKey]
|
||||||
|
* @property {string} [archiveApiUrl]
|
||||||
|
* @property {string} [archiveApiKey]
|
||||||
|
* @property {string} [systemPrefix]
|
||||||
|
* @property {string|null} [agreementId]
|
||||||
|
* @property {boolean} [debug]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} SerializedRun
|
||||||
|
* @property {string} [name]
|
||||||
|
* @property {number} [start_time]
|
||||||
|
* @property {number} [end_time]
|
||||||
|
* @property {string} [trace_id]
|
||||||
|
* @property {any} [inputs]
|
||||||
|
* @property {any} [outputs]
|
||||||
|
* @property {{ metadata?: { ls_provider?: string, ls_model_name?: string } }} [extra]
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends {LangChainTracer}
|
||||||
|
*/
|
||||||
|
class JLINCTracer extends LangChainTracer {
|
||||||
|
/**
|
||||||
|
* @param {JLINCTracerFields} [fields={}]
|
||||||
|
*/
|
||||||
|
constructor(fields = {}) {
|
||||||
|
super(fields);
|
||||||
|
const defaultDataStoreApiUrl = "https://api-test.jlinc.io";
|
||||||
|
const defaultDataStoreApiKey = "";
|
||||||
|
const defaultArchiveApiUrl = "https://archive-test.jlinc.io";
|
||||||
|
const defaultArchiveApiKey = "";
|
||||||
|
const defaultSystemPrefix = "MyProject";
|
||||||
|
|
||||||
|
/** @type {string} */
|
||||||
|
this.dataStoreApiUrl = fields.dataStoreApiUrl ?? defaultDataStoreApiUrl;
|
||||||
|
/** @type {string} */
|
||||||
|
this.dataStoreApiKey = fields.dataStoreApiKey ?? defaultDataStoreApiKey;
|
||||||
|
/** @type {string} */
|
||||||
|
this.archiveApiUrl = fields.archiveApiUrl ?? defaultArchiveApiUrl;
|
||||||
|
/** @type {string} */
|
||||||
|
this.archiveApiKey = fields.archiveApiKey ?? defaultArchiveApiKey;
|
||||||
|
/** @type {string} */
|
||||||
|
this.systemPrefix = this._sanitize(fields.systemPrefix ?? defaultSystemPrefix);
|
||||||
|
/** @type {string|null} */
|
||||||
|
this.agreementId = fields.agreementId ?? null;
|
||||||
|
/** @type {boolean} */
|
||||||
|
this.debug = fields.debug ?? false;
|
||||||
|
|
||||||
|
/** @type {string|null} */
|
||||||
|
this.domain = null;
|
||||||
|
/** @type {Set<string>} */
|
||||||
|
this.entities = new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} run
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async onRunCreate(run) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} run
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async onRunUpdate(run) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async getDefaultProjectName() {
|
||||||
|
return this.systemPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async onLLMStart(serialized) {
|
||||||
|
if (this.debug) {
|
||||||
|
console.log(`\nJLINC: onLLMStart`);
|
||||||
|
console.log(`---------------------------------------------`);
|
||||||
|
}
|
||||||
|
await this._jlincTrace({
|
||||||
|
event: "llm_start",
|
||||||
|
name: serialized?.name || "unknown",
|
||||||
|
ts: serialized?.start_time,
|
||||||
|
provider: serialized?.extra?.metadata,
|
||||||
|
traceId: serialized?.trace_id,
|
||||||
|
inputs: serialized?.inputs,
|
||||||
|
}, 'out');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async onLLMEnd(serialized) {
|
||||||
|
if (this.debug) {
|
||||||
|
console.log(`\nJLINC: onLLMEnd`);
|
||||||
|
console.log(`---------------------------------------------`);
|
||||||
|
}
|
||||||
|
await this._jlincTrace({
|
||||||
|
event: "llm_end",
|
||||||
|
name: serialized?.name || "unknown",
|
||||||
|
ts: serialized?.end_time,
|
||||||
|
provider: serialized?.extra?.metadata,
|
||||||
|
traceId: serialized?.trace_id,
|
||||||
|
outputs: serialized?.outputs,
|
||||||
|
}, 'in');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async onToolStart(serialized) {
|
||||||
|
if (this.debug) {
|
||||||
|
console.log(`\nJLINC: onToolStart`);
|
||||||
|
console.log(`---------------------------------------------`);
|
||||||
|
}
|
||||||
|
await this._jlincTrace({
|
||||||
|
event: "tool_start",
|
||||||
|
name: serialized?.name || "unknown",
|
||||||
|
ts: serialized?.start_time,
|
||||||
|
provider: serialized?.extra?.metadata,
|
||||||
|
traceId: serialized?.trace_id,
|
||||||
|
inputs: serialized?.inputs,
|
||||||
|
}, 'out');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {SerializedRun} serialized
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async onToolEnd(serialized) {
|
||||||
|
if (this.debug) {
|
||||||
|
console.log(`\nJLINC: onToolEnd`);
|
||||||
|
console.log(`---------------------------------------------`);
|
||||||
|
}
|
||||||
|
await this._jlincTrace({
|
||||||
|
event: "tool_end",
|
||||||
|
name: serialized?.name || "unknown",
|
||||||
|
ts: serialized?.end_time,
|
||||||
|
provider: serialized?.extra?.metadata,
|
||||||
|
traceId: serialized?.trace_id,
|
||||||
|
outputs: serialized?.outputs,
|
||||||
|
}, 'in');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} dir
|
||||||
|
* @param {any} payload
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
async _postToApi(dir, payload) {
|
||||||
|
const response = await axios.post(
|
||||||
|
`${this.dataStoreApiUrl}/api/v1/data/${dir}`,
|
||||||
|
payload,
|
||||||
|
{
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${this.dataStoreApiKey}`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} entityShortName
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async _setEntity(entityShortName) {
|
||||||
|
if (!this.entities.has(entityShortName)) {
|
||||||
|
let recipient = null;
|
||||||
|
try {
|
||||||
|
recipient = await this._postToApi(`entity/get`, { shortName: entityShortName });
|
||||||
|
} catch (e) {
|
||||||
|
recipient = await this._postToApi(`entity/create`, { shortName: entityShortName });
|
||||||
|
}
|
||||||
|
this.entities.add(entityShortName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} input
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
_sanitize(input) {
|
||||||
|
return input.replace(/[^a-zA-Z0-9._-]/g, '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {any} payload
|
||||||
|
* @param {'in' | 'out'} direction
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
async _jlincTrace(payload, direction) {
|
||||||
|
try {
|
||||||
|
if (!this.domain) {
|
||||||
|
const domains = await this._postToApi(`entity/domains/get`, {});
|
||||||
|
this.domain = domains[0];
|
||||||
|
}
|
||||||
|
let entityShortName = `${this.systemPrefix}-${this._sanitize(payload.name)}`;
|
||||||
|
payload?.provider?.ls_provider && (entityShortName += `-${this._sanitize(payload.provider.ls_provider)}`);
|
||||||
|
payload?.provider?.ls_model_name && (entityShortName += `-${this._sanitize(payload.provider.ls_model_name)}`);
|
||||||
|
entityShortName += `@${this.domain}`;
|
||||||
|
await this._setEntity(entityShortName);
|
||||||
|
const systemShortName = `${this.systemPrefix}-system@${this.domain}`;
|
||||||
|
await this._setEntity(systemShortName);
|
||||||
|
const recipientShortName = direction === 'in' ? systemShortName : entityShortName;
|
||||||
|
const senderShortName = direction === 'out' ? systemShortName : entityShortName;
|
||||||
|
const data = {
|
||||||
|
type: 'data',
|
||||||
|
senderShortName,
|
||||||
|
recipientShortName,
|
||||||
|
agreementId: this.agreementId,
|
||||||
|
data: payload,
|
||||||
|
archive: {
|
||||||
|
url: this.archiveApiUrl,
|
||||||
|
key: this.archiveApiKey,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const event = await this._postToApi(`event/produce`, data);
|
||||||
|
if (this.debug) {
|
||||||
|
console.log(JSON.stringify({ event }, null, 2));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("[Tracer] Failed to log event:", error.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { JLINCTracer }
|
||||||
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "jlinc-tracer",
|
"name": "@jlinc/langchain",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "jlinc-tracer",
|
"name": "@jlinc/langchain",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"description": "A LangChain callback plugin that logs events to the JLINC API.",
|
"description": "A LangChain plugin that logs events to the JLINC API.",
|
||||||
"main": "dist/tracer.js",
|
"main": "dist/tracer.js",
|
||||||
"types": "dist/tracer.d.ts",
|
"types": "dist/tracer.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Reference in New Issue
Block a user