Skip to content

Commit

Permalink
add metadata headers
Browse files Browse the repository at this point in the history
  • Loading branch information
capaj authored and rychlis committed Apr 11, 2024
1 parent a46b7e4 commit 2f973cd
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 35 deletions.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@langtail/node",
"version": "0.1.4",
"version": "0.1.5",
"description": "",
"main": "./dist/LangtailNode.js",
"packageManager": "[email protected]",
Expand Down Expand Up @@ -29,12 +29,12 @@
],
"license": "MIT",
"devDependencies": {
"@types/node": "^20.12.5",
"@types/node": "^20.12.7",
"dotenv": "^16.4.5",
"nock": "14.0.0-beta.5",
"prettier": "^3.2.5",
"tsup": "^8.0.2",
"typescript": "^5.4.4",
"typescript": "^5.4.5",
"vitest": "^1.4.0",
"zod": "^3.22.4"
},
Expand Down
42 changes: 21 additions & 21 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 24 additions & 1 deletion src/LangtailNode.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ describe("LangtailNode", () => {
],
stream: true,
model: "gpt-3.5-turbo",

doNotRecord: false,
metadata: {
"custom-field": 1,
},
Expand All @@ -35,6 +35,26 @@ describe("LangtailNode", () => {
.post("/chat/completions")
.reply(200, function (uri, req) {
expect(this.req.headers["x-langtail-do-not-record"][0]).toBe("true")
expect(this.req.headers["x-langtail-metadata-custom-field"][0]).toBe(
"1",
)

// check that body has no metadata or doNotRecord
expect(req).toMatchInlineSnapshot(`
{
"messages": [
{
"content": "You are a helpful assistant.",
"role": "system",
},
{
"content": "What is the weather like?",
"role": "user",
},
],
"model": "gpt-3.5-turbo",
}
`)
})
await lt.chat.completions.create({
messages: [
Expand All @@ -44,6 +64,9 @@ describe("LangtailNode", () => {

model: "gpt-3.5-turbo",
doNotRecord: true,
metadata: {
"custom-field": 1,
},
})

expect(nock.pendingMocks()).toEqual([])
Expand Down
30 changes: 25 additions & 5 deletions src/LangtailNode.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import OpenAI from "openai"
import * as Core from "openai/core"
import { LangtailPrompts } from "./LangtailPrompts"
import { ChatCompletionCreateParamsStreaming } from "openai/resources/index"
import {
ChatCompletionCreateParamsStreaming,
Completions,
} from "openai/resources/index"
import {
ChatCompletion,
ChatCompletionChunk,
Expand Down Expand Up @@ -50,7 +53,7 @@ export class LangtailNode {
doNotRecord?: boolean
organization?: string
project?: string
fetch: Core.Fetch
fetch?: Core.Fetch
}) {
const organization = options?.organization

Expand Down Expand Up @@ -87,15 +90,32 @@ export class LangtailNode {
this.chat = {
completions: {
// @ts-expect-error
create: (params, options) => {
create: (
params: ChatCompletionCreateParamsBase & ILangtailExtraProps,
options: Core.RequestOptions = {},
) => {
if (params.doNotRecord) {
options = options ?? {}
options.headers = {
["x-langtail-do-not-record"]: "true",
...options?.headers,
}
delete params.doNotRecord // openAI does not support this parameter
}
delete params.doNotRecord // openAI does not support these parameters

if (params.metadata) {
const metadataHeaders = Object.entries(params.metadata).reduce(
(acc, [key, value]) => {
acc[`x-langtail-metadata-${key}`] = value
return acc
},
{},
)
options.headers = {
...metadataHeaders,
...options?.headers,
}
}
delete params.metadata

return this._open_ai.chat.completions.create(params, options)
},
Expand Down
6 changes: 5 additions & 1 deletion src/LangtailPrompts.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import "dotenv/config"
import { describe, expect, it } from "vitest"
import nock from "nock"

import { LangtailPrompts } from "./LangtailPrompts"
import { openAIStreamingResponseSchema } from "./dataSchema"

Expand Down Expand Up @@ -104,6 +104,7 @@ describe(
project: "ci-tests-project",
fetch: async (url, init) => {
expect(init?.headers?.["x-langtail-do-not-record"]).toBe("true")
expect(init?.headers?.["x-langtail-metadata-custom-field"]).toBe(1)

return {
ok: true,
Expand All @@ -128,6 +129,9 @@ describe(
about: "napoleon",
},
doNotRecord: true,
metadata: {
"custom-field": 1,
},
})

expect(res.httpResponse.status).toBe(200)
Expand Down
14 changes: 10 additions & 4 deletions src/LangtailPrompts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ import { Stream } from "openai/streaming"
import { ILangtailExtraProps } from "./LangtailNode"
import { Fetch } from "openai/core"

export type Environment =
| "preview"
| "staging"
| "production"
export type Environment = "preview" | "staging" | "production"

interface LangtailPromptVariables {} // TODO use this when generating schema for deployed prompts

Expand Down Expand Up @@ -93,14 +90,23 @@ export class LangtailPrompts {
prompt,
environment,
doNotRecord,
metadata,
...rest
}: IRequestParams | IRequestParamsStream) {
const metadataHeaders = metadata
? Object.entries(metadata).reduce((acc, [key, value]) => {
acc[`x-langtail-metadata-${key}`] = value
return acc
}, {})
: {}

const fetchInit = {
method: "POST",
headers: {
"X-API-Key": this.apiKey,
"content-type": "application/json",
"x-langtail-do-not-record": doNotRecord ? "true" : "false",
...metadataHeaders,
},
body: JSON.stringify({ stream: false, ...rest }),
}
Expand Down

0 comments on commit 2f973cd

Please sign in to comment.