Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nc/tracer session ensure #1238

Merged
merged 3 commits into from
May 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 2 additions & 10 deletions langchain/src/callbacks/handlers/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ export async function getTracingCallbackHandler(
return tracer;
}

export async function getTracingV2CallbackHandler(
session?: string
): Promise<LangChainTracer> {
const tracer = new LangChainTracer();
if (session) {
await tracer.loadSession(session);
} else {
await tracer.loadDefaultSession();
}
return tracer;
export async function getTracingV2CallbackHandler(): Promise<LangChainTracer> {
return new LangChainTracer();
}
140 changes: 59 additions & 81 deletions langchain/src/callbacks/handlers/tracer_langchain.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import * as uuid from "uuid";

import { BaseTracer, Run, BaseRun } from "./tracer.js";
import { Optional } from "../../types/type-utils.js";

export interface RunCreate extends BaseRun {
child_runs: this[];
Expand All @@ -25,7 +22,17 @@ export interface TracerSession extends BaseTracerSessionV2 {
id: string; // uuid
}

export class LangChainTracer extends BaseTracer {
export interface LangChainTracerFields {
exampleId?: string;
tenantId?: string;
sessionName?: string;
sessionExtra?: Record<string, unknown>;
}

export class LangChainTracer
extends BaseTracer
implements LangChainTracerFields
{
name = "langchain_tracer";

protected endpoint =
Expand All @@ -38,13 +45,22 @@ export class LangChainTracer extends BaseTracer {
"Content-Type": "application/json",
};

sessionName: string;

sessionExtra?: LangChainTracerFields["sessionExtra"];

protected session: TracerSession;

exampleId?: string;

tenantId?: string;

constructor(exampleId?: string, tenantId?: string) {
constructor({
exampleId,
tenantId,
sessionName,
sessionExtra,
}: LangChainTracerFields = {}) {
super();

// eslint-disable-next-line no-process-env
Expand All @@ -59,65 +75,56 @@ export class LangChainTracer extends BaseTracer {
? // eslint-disable-next-line no-process-env
process.env?.LANGCHAIN_TENANT_ID
: undefined);
this.sessionName =
sessionName ??
(typeof process !== "undefined"
? // eslint-disable-next-line no-process-env
process.env?.LANGCHAIN_SESSION
: undefined) ??
"default";
this.sessionExtra = sessionExtra;
this.exampleId = exampleId;
}

async newSession(sessionName?: string): Promise<TracerSession> {
const tenantId = this.tenantId ?? (await this.updateTenantId());
const sessionCreate: TracerSessionCreateV2 = {
start_time: Date.now(),
name: sessionName,
tenant_id: tenantId,
};
const session = await this.persistSession(sessionCreate);
this.session = session;
return session as TracerSession;
}

async loadSession(sessionName: string): Promise<TracerSession> {
const endpoint = `${this.endpoint}/sessions?name=${sessionName}`;
return this._handleSessionResponse(endpoint);
}

async loadDefaultSession(): Promise<TracerSession> {
const endpoint = `${this.endpoint}/sessions?name=default`;
return this._handleSessionResponse(endpoint);
}

protected async persistSession(
sessionCreate: Optional<BaseTracerSessionV2, "tenant_id">
): Promise<TracerSession> {
const endpoint = `${this.endpoint}/sessions`;
const tenant_id = this.tenantId ?? (await this.updateTenantId());
const response = await fetch(endpoint, {
protected async ensureSession(): Promise<TracerSession> {
if (this.session) {
return this.session;
}
const tenantId = await this.ensureTenantId();
const endpoint = `${this.endpoint}/sessions?upsert=true`;
const res = await fetch(endpoint, {
method: "POST",
headers: this.headers,
body: JSON.stringify(sessionCreate),
body: JSON.stringify({
name: this.sessionName,
tenant_id: tenantId,
extra: this.sessionExtra,
}),
});
if (!response.ok) {
if (sessionCreate.name !== undefined) {
return await this.loadSession(sessionCreate.name);
} else {
return await this.loadDefaultSession();
}
if (!res.ok) {
const body = await res.text();
throw new Error(
`Failed to create session: ${res.status} ${res.statusText} ${body}`
);
}
return {
id: (await response.json()).id,
tenant_id,
...sessionCreate,
};
const session = await res.json();
this.session = session;
return session;
}

async updateTenantId(): Promise<string> {
protected async ensureTenantId(): Promise<string> {
if (this.tenantId) {
return this.tenantId;
}
const endpoint = `${this.endpoint}/tenants`;
const response = await fetch(endpoint, {
method: "GET",
headers: this.headers,
});

if (!response.ok) {
const body = await response.text();
throw new Error(
`Failed to fetch tenant ID: ${response.status} ${response.statusText}`
`Failed to fetch tenant ID: ${response.status} ${response.statusText} ${body}`
);
}

Expand All @@ -131,41 +138,11 @@ export class LangChainTracer extends BaseTracer {
return tenantId;
}

protected async _handleSessionResponse(
endpoint: string
): Promise<TracerSession> {
const tenantId = this.tenantId ?? (await this.updateTenantId());
const configured_endpoint = `${endpoint}&tenant_id=${this.tenantId}`;
const response = await fetch(configured_endpoint, {
method: "GET",
headers: this.headers,
});
let tracerSession: TracerSession;
if (!response.ok) {
throw new Error(
`Failed to fetch session: ${response.status} ${response.statusText}`
);
}
const resp = (await response.json()) as TracerSession[];
if (resp.length === 0) {
tracerSession = {
id: uuid.v4(),
start_time: Date.now(),
tenant_id: tenantId,
};
this.session = tracerSession;
return tracerSession;
}
[tracerSession] = resp;
this.session = tracerSession;
return tracerSession;
}

private async _convertToCreate(
run: Run,
example_id: string | undefined = undefined
): Promise<RunCreate> {
const session = this.session ?? (await this.loadDefaultSession());
const session = await this.ensureSession();
const persistedRun: RunCreate = {
id: run.id,
name: run.name,
Expand Down Expand Up @@ -199,8 +176,9 @@ export class LangChainTracer extends BaseTracer {
body: JSON.stringify(persistedRun),
});
if (!response.ok) {
console.error(
`Failed to persist run: ${response.status} ${response.statusText}`
const body = await response.text();
throw new Error(
`Failed to persist run: ${response.status} ${response.statusText} ${body}`
);
}
}
Expand Down
15 changes: 6 additions & 9 deletions langchain/src/callbacks/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -528,17 +528,14 @@ export class CallbackManager
(handler) => handler.name === "langchain_tracer"
)
) {
const session =
typeof process !== "undefined"
? // eslint-disable-next-line no-process-env
process.env?.LANGCHAIN_SESSION
: undefined;
if (tracingV2Enabled) {
callbackManager.addHandler(
await getTracingV2CallbackHandler(session),
true
);
callbackManager.addHandler(await getTracingV2CallbackHandler(), true);
} else {
const session =
typeof process !== "undefined"
? // eslint-disable-next-line no-process-env
process.env?.LANGCHAIN_SESSION
: undefined;
callbackManager.addHandler(
await getTracingCallbackHandler(session),
true
Expand Down
6 changes: 4 additions & 2 deletions langchain/src/callbacks/tests/langchain_tracer.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@ import { HumanChatMessage } from "../../schema/index.js";
import { ChatOpenAI } from "../../chat_models/openai.js";

test("Test LangChain V2 tracer", async () => {
const tracer = new LangChainTracer();
await tracer.newSession(`Some Session Name - ${uuid.v4()}`);
const tracer = new LangChainTracer({
sessionName: `JS Int Test - ${uuid.v4()}`,
sessionExtra: { source: "langchain-js" },
});
const chainRunId = uuid.v4();
const toolRunId = uuid.v4();
const llmRunId = uuid.v4();
Expand Down
7 changes: 4 additions & 3 deletions langchain/src/client/langchainplus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -454,11 +454,12 @@ export class LangChainPlusClient {
sessionName_ = sessionName;
}
const results: DatasetRunResults = {};
await new LangChainTracer().newSession(sessionName_);
await Promise.all(
examples.map(async (example) => {
const tracer = new LangChainTracer(example.id);
await tracer.loadSession(sessionName_);
const tracer = new LangChainTracer({
exampleId: example.id,
sessionName: sessionName_,
});
if (isLLM(llmOrChain)) {
const llmResult = await this.runLLM(
example,
Expand Down