@langchain/openai 1.7.1 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/azure/chat_models/common.cjs +1 -2
- package/dist/azure/chat_models/common.d.cts +1 -3
- package/dist/azure/chat_models/common.d.cts.map +1 -1
- package/dist/azure/chat_models/common.d.ts +1 -3
- package/dist/azure/chat_models/common.d.ts.map +1 -1
- package/dist/azure/chat_models/common.js +1 -2
- package/dist/azure/chat_models/completions.cjs +1 -2
- package/dist/azure/chat_models/completions.d.cts +1 -3
- package/dist/azure/chat_models/completions.d.cts.map +1 -1
- package/dist/azure/chat_models/completions.d.ts +1 -3
- package/dist/azure/chat_models/completions.d.ts.map +1 -1
- package/dist/azure/chat_models/completions.js +1 -2
- package/dist/azure/chat_models/index.cjs +2 -3
- package/dist/azure/chat_models/index.d.cts +1 -3
- package/dist/azure/chat_models/index.d.cts.map +1 -1
- package/dist/azure/chat_models/index.d.ts +1 -3
- package/dist/azure/chat_models/index.d.ts.map +1 -1
- package/dist/azure/chat_models/index.js +2 -3
- package/dist/azure/chat_models/responses.cjs +2 -3
- package/dist/azure/chat_models/responses.d.cts +1 -3
- package/dist/azure/chat_models/responses.d.cts.map +1 -1
- package/dist/azure/chat_models/responses.d.ts +1 -3
- package/dist/azure/chat_models/responses.d.ts.map +1 -1
- package/dist/azure/chat_models/responses.js +2 -3
- package/dist/azure/embeddings.cjs +3 -4
- package/dist/azure/embeddings.d.cts +1 -3
- package/dist/azure/embeddings.d.cts.map +1 -1
- package/dist/azure/embeddings.d.ts +1 -3
- package/dist/azure/embeddings.d.ts.map +1 -1
- package/dist/azure/embeddings.js +3 -4
- package/dist/azure/llms.cjs +2 -3
- package/dist/azure/llms.d.cts +1 -3
- package/dist/azure/llms.d.cts.map +1 -1
- package/dist/azure/llms.d.ts +1 -3
- package/dist/azure/llms.d.ts.map +1 -1
- package/dist/azure/llms.js +2 -3
- package/dist/chat_models/base.cjs +5 -6
- package/dist/chat_models/base.d.cts +1 -3
- package/dist/chat_models/base.d.cts.map +1 -1
- package/dist/chat_models/base.d.ts +1 -3
- package/dist/chat_models/base.d.ts.map +1 -1
- package/dist/chat_models/base.js +5 -6
- package/dist/chat_models/completions.cjs +1 -2
- package/dist/chat_models/completions.d.cts +1 -2
- package/dist/chat_models/completions.d.cts.map +1 -1
- package/dist/chat_models/completions.d.ts +1 -2
- package/dist/chat_models/completions.d.ts.map +1 -1
- package/dist/chat_models/completions.js +1 -2
- package/dist/chat_models/index.cjs +3 -4
- package/dist/chat_models/index.d.cts +3 -5
- package/dist/chat_models/index.d.cts.map +1 -1
- package/dist/chat_models/index.d.ts +3 -5
- package/dist/chat_models/index.d.ts.map +1 -1
- package/dist/chat_models/index.js +3 -4
- package/dist/chat_models/profiles.cjs +1 -2
- package/dist/chat_models/profiles.js +1 -2
- package/dist/chat_models/responses.cjs +3 -4
- package/dist/chat_models/responses.d.cts +1 -3
- package/dist/chat_models/responses.d.cts.map +1 -1
- package/dist/chat_models/responses.d.ts +1 -3
- package/dist/chat_models/responses.d.ts.map +1 -1
- package/dist/chat_models/responses.js +3 -4
- package/dist/converters/completions.cjs +2 -3
- package/dist/converters/completions.d.cts +0 -2
- package/dist/converters/completions.d.cts.map +1 -1
- package/dist/converters/completions.d.ts +0 -2
- package/dist/converters/completions.d.ts.map +1 -1
- package/dist/converters/completions.js +2 -3
- package/dist/converters/responses.cjs +2 -4
- package/dist/converters/responses.cjs.map +1 -1
- package/dist/converters/responses.d.cts +1 -2
- package/dist/converters/responses.d.cts.map +1 -1
- package/dist/converters/responses.d.ts +1 -2
- package/dist/converters/responses.d.ts.map +1 -1
- package/dist/converters/responses.js +2 -4
- package/dist/converters/responses.js.map +1 -1
- package/dist/decisions/index.cjs +98 -0
- package/dist/decisions/index.cjs.map +1 -0
- package/dist/decisions/index.d.cts +50 -0
- package/dist/decisions/index.d.cts.map +1 -0
- package/dist/decisions/index.d.ts +50 -0
- package/dist/decisions/index.d.ts.map +1 -0
- package/dist/decisions/index.js +98 -0
- package/dist/decisions/index.js.map +1 -0
- package/dist/decisions/input.cjs +122 -0
- package/dist/decisions/input.cjs.map +1 -0
- package/dist/decisions/input.js +122 -0
- package/dist/decisions/input.js.map +1 -0
- package/dist/decisions/types.cjs +28 -0
- package/dist/decisions/types.cjs.map +1 -0
- package/dist/decisions/types.d.cts +58 -0
- package/dist/decisions/types.d.cts.map +1 -0
- package/dist/decisions/types.d.ts +58 -0
- package/dist/decisions/types.d.ts.map +1 -0
- package/dist/decisions/types.js +28 -0
- package/dist/decisions/types.js.map +1 -0
- package/dist/embeddings.cjs +2 -3
- package/dist/embeddings.d.cts +0 -2
- package/dist/embeddings.d.cts.map +1 -1
- package/dist/embeddings.d.ts +0 -2
- package/dist/embeddings.d.ts.map +1 -1
- package/dist/embeddings.js +2 -3
- package/dist/index.cjs +40 -38
- package/dist/index.d.cts +10 -8
- package/dist/index.d.ts +10 -8
- package/dist/index.js +16 -15
- package/dist/llms.cjs +3 -4
- package/dist/llms.d.cts +0 -2
- package/dist/llms.d.cts.map +1 -1
- package/dist/llms.d.ts +0 -2
- package/dist/llms.d.ts.map +1 -1
- package/dist/llms.js +3 -4
- package/dist/tools/applyPatch.cjs +1 -2
- package/dist/tools/applyPatch.d.cts +0 -2
- package/dist/tools/applyPatch.d.cts.map +1 -1
- package/dist/tools/applyPatch.d.ts +0 -2
- package/dist/tools/applyPatch.d.ts.map +1 -1
- package/dist/tools/applyPatch.js +1 -2
- package/dist/tools/codeInterpreter.cjs +1 -2
- package/dist/tools/codeInterpreter.d.cts +0 -2
- package/dist/tools/codeInterpreter.d.cts.map +1 -1
- package/dist/tools/codeInterpreter.d.ts +0 -2
- package/dist/tools/codeInterpreter.d.ts.map +1 -1
- package/dist/tools/codeInterpreter.js +1 -2
- package/dist/tools/computerUse.cjs +1 -2
- package/dist/tools/computerUse.d.cts +0 -2
- package/dist/tools/computerUse.d.cts.map +1 -1
- package/dist/tools/computerUse.d.ts +0 -2
- package/dist/tools/computerUse.d.ts.map +1 -1
- package/dist/tools/computerUse.js +1 -2
- package/dist/tools/custom.cjs +1 -2
- package/dist/tools/custom.d.cts +0 -2
- package/dist/tools/custom.d.cts.map +1 -1
- package/dist/tools/custom.d.ts +0 -2
- package/dist/tools/custom.d.ts.map +1 -1
- package/dist/tools/custom.js +1 -2
- package/dist/tools/dalle.cjs +1 -2
- package/dist/tools/dalle.d.cts +0 -2
- package/dist/tools/dalle.d.cts.map +1 -1
- package/dist/tools/dalle.d.ts +0 -2
- package/dist/tools/dalle.d.ts.map +1 -1
- package/dist/tools/dalle.js +1 -2
- package/dist/tools/fileSearch.cjs +1 -2
- package/dist/tools/fileSearch.d.cts +0 -2
- package/dist/tools/fileSearch.d.cts.map +1 -1
- package/dist/tools/fileSearch.d.ts +0 -2
- package/dist/tools/fileSearch.d.ts.map +1 -1
- package/dist/tools/fileSearch.js +1 -2
- package/dist/tools/imageGeneration.cjs +1 -2
- package/dist/tools/imageGeneration.d.cts +0 -2
- package/dist/tools/imageGeneration.d.cts.map +1 -1
- package/dist/tools/imageGeneration.d.ts +0 -2
- package/dist/tools/imageGeneration.d.ts.map +1 -1
- package/dist/tools/imageGeneration.js +1 -2
- package/dist/tools/index.cjs +1 -2
- package/dist/tools/index.d.cts +0 -2
- package/dist/tools/index.d.cts.map +1 -1
- package/dist/tools/index.d.ts +0 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -2
- package/dist/tools/localShell.cjs +1 -2
- package/dist/tools/localShell.d.cts +0 -2
- package/dist/tools/localShell.d.cts.map +1 -1
- package/dist/tools/localShell.d.ts +0 -2
- package/dist/tools/localShell.d.ts.map +1 -1
- package/dist/tools/localShell.js +1 -2
- package/dist/tools/mcp.cjs +1 -2
- package/dist/tools/mcp.d.cts +1 -2
- package/dist/tools/mcp.d.cts.map +1 -1
- package/dist/tools/mcp.d.ts +1 -2
- package/dist/tools/mcp.d.ts.map +1 -1
- package/dist/tools/mcp.js +1 -2
- package/dist/tools/shell.cjs +1 -2
- package/dist/tools/shell.d.cts +0 -2
- package/dist/tools/shell.d.cts.map +1 -1
- package/dist/tools/shell.d.ts +0 -2
- package/dist/tools/shell.d.ts.map +1 -1
- package/dist/tools/shell.js +1 -2
- package/dist/tools/toolSearch.cjs +1 -2
- package/dist/tools/toolSearch.d.cts +0 -2
- package/dist/tools/toolSearch.d.cts.map +1 -1
- package/dist/tools/toolSearch.d.ts +0 -2
- package/dist/tools/toolSearch.d.ts.map +1 -1
- package/dist/tools/toolSearch.js +1 -2
- package/dist/tools/webSearch.cjs +1 -2
- package/dist/tools/webSearch.d.cts +0 -2
- package/dist/tools/webSearch.d.cts.map +1 -1
- package/dist/tools/webSearch.d.ts +0 -2
- package/dist/tools/webSearch.d.ts.map +1 -1
- package/dist/tools/webSearch.js +1 -2
- package/dist/types.d.cts +0 -2
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.ts +0 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/azure.cjs +1 -2
- package/dist/utils/azure.d.cts +1 -2
- package/dist/utils/azure.d.cts.map +1 -1
- package/dist/utils/azure.d.ts +1 -2
- package/dist/utils/azure.d.ts.map +1 -1
- package/dist/utils/azure.js +1 -2
- package/dist/utils/client.cjs +1 -2
- package/dist/utils/client.d.cts +0 -2
- package/dist/utils/client.d.cts.map +1 -1
- package/dist/utils/client.d.ts +0 -2
- package/dist/utils/client.d.ts.map +1 -1
- package/dist/utils/client.js +1 -2
- package/dist/utils/errors.cjs +1 -2
- package/dist/utils/errors.js +1 -2
- package/dist/utils/misc.cjs +1 -2
- package/dist/utils/misc.d.cts +0 -2
- package/dist/utils/misc.d.cts.map +1 -1
- package/dist/utils/misc.d.ts +0 -2
- package/dist/utils/misc.d.ts.map +1 -1
- package/dist/utils/misc.js +1 -2
- package/dist/utils/output.cjs +1 -2
- package/dist/utils/output.js +1 -2
- package/dist/utils/profile.cjs +1 -2
- package/dist/utils/profile.js +1 -2
- package/dist/utils/prompts.cjs +1 -2
- package/dist/utils/prompts.d.cts +0 -2
- package/dist/utils/prompts.d.cts.map +1 -1
- package/dist/utils/prompts.d.ts +0 -2
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +1 -2
- package/dist/utils/responses_stream_events.cjs +2 -2
- package/dist/utils/responses_stream_events.cjs.map +1 -1
- package/dist/utils/responses_stream_events.d.cts +1 -2
- package/dist/utils/responses_stream_events.d.cts.map +1 -1
- package/dist/utils/responses_stream_events.d.ts +1 -2
- package/dist/utils/responses_stream_events.d.ts.map +1 -1
- package/dist/utils/responses_stream_events.js +2 -2
- package/dist/utils/responses_stream_events.js.map +1 -1
- package/dist/utils/stream_events.js +1 -2
- package/dist/utils/tools.cjs +1 -2
- package/dist/utils/tools.d.cts +0 -2
- package/dist/utils/tools.d.cts.map +1 -1
- package/dist/utils/tools.d.ts +0 -2
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +1 -2
- package/package.json +10 -10
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":["OpenAIClient"],"sources":["../../src/decisions/index.ts"],"mappings":";;;iBAkCiB;;EAEf;;;;;EAKA;;;;;;EAMA,gBAAgB,KAAK;;;;;;;;;;;;;;;;;;;;;;;qBAwBV,wBAAwB,SAAS,iBAAiB;SACtD;EAIP;WAES;YAEC,QAAQA;EAElB,YAAY,eAAe,SAAS,KAAK;EACzC,YAAY,QAAQ;EA8Bd,aAAa,UAAU,WAC3B,SAAS,gBAAgB,IACzB,UAAU,QAAQ,kBACjB,QAAQ,eAAe"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { Answer, AnswerFor, Answers, Choice, ChoiceAnswer, DecisionInput, DecisionRequest, DecisionResult, Level, Predicate, PredicateAnswer, Question, Questions, RefusalAnswer, Score, ScoreAnswer } from "./types.js";
|
|
2
|
+
import { ClientOptions, OpenAI } from "openai";
|
|
3
|
+
import { Runnable, RunnableConfig } from "@langchain/core/runnables";
|
|
4
|
+
export interface OpenAIDecisionsFields {
|
|
5
|
+
/** Decisions model name, such as `gpt-6-luna`. */
|
|
6
|
+
model: string;
|
|
7
|
+
/**
|
|
8
|
+
* Falls back to the LangSmith gateway key when routing through the gateway, then
|
|
9
|
+
* to the `OPENAI_API_KEY` environment variable.
|
|
10
|
+
*/
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
/**
|
|
13
|
+
* OpenAI SDK client options, such as `baseURL`, `timeout` or `fetch`. Without a
|
|
14
|
+
* `baseURL`, `OPENAI_API_BASE` or `OPENAI_BASE_URL`, setting `LANGSMITH_GATEWAY`
|
|
15
|
+
* routes requests through the LangSmith gateway, as with `ChatOpenAI`.
|
|
16
|
+
*/
|
|
17
|
+
configuration?: Omit<ClientOptions, "apiKey">;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Ask typed questions about text, messages or JSON state with the OpenAI Decisions
|
|
21
|
+
* API (beta). Answer types are inferred from the questions passed to `invoke`.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```ts
|
|
25
|
+
* const decisions = new OpenAIDecisions({ model: "gpt-6-luna" });
|
|
26
|
+
* const { answers } = await decisions.invoke({
|
|
27
|
+
* input: "I was charged twice!",
|
|
28
|
+
* questions: {
|
|
29
|
+
* urgent: { type: "predicate", instructions: "Is this urgent?" },
|
|
30
|
+
* team: {
|
|
31
|
+
* type: "choice",
|
|
32
|
+
* instructions: "Which team should handle this?",
|
|
33
|
+
* choices: { billing: "Payments", technical: null },
|
|
34
|
+
* },
|
|
35
|
+
* },
|
|
36
|
+
* });
|
|
37
|
+
* if (answers.team.type === "choice") answers.team.choice; // "billing" | "technical"
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare class OpenAIDecisions extends Runnable<DecisionRequest, DecisionResult> {
|
|
41
|
+
static lc_name(): string;
|
|
42
|
+
lc_namespace: string[];
|
|
43
|
+
readonly model: string;
|
|
44
|
+
protected client: OpenAI;
|
|
45
|
+
constructor(model: string, fields?: Omit<OpenAIDecisionsFields, "model">);
|
|
46
|
+
constructor(fields: OpenAIDecisionsFields);
|
|
47
|
+
invoke<const Q extends Questions>(request: DecisionRequest<Q>, options?: Partial<RunnableConfig>): Promise<DecisionResult<Q>>;
|
|
48
|
+
}
|
|
49
|
+
export type { Answer, AnswerFor, Answers, Choice, ChoiceAnswer, DecisionInput, DecisionRequest, DecisionResult, Level, Predicate, PredicateAnswer, Question, Questions, RefusalAnswer, Score, ScoreAnswer };
|
|
50
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":["OpenAIClient"],"sources":["../../src/decisions/index.ts"],"mappings":";;;iBAkCiB;;EAEf;;;;;EAKA;;;;;;EAMA,gBAAgB,KAAK;;;;;;;;;;;;;;;;;;;;;;;qBAwBV,wBAAwB,SAAS,iBAAiB;SACtD;EAIP;WAES;YAEC,QAAQA;EAElB,YAAY,eAAe,SAAS,KAAK;EACzC,YAAY,QAAQ;EA8Bd,aAAa,UAAU,WAC3B,SAAS,gBAAgB,IACzB,UAAU,QAAQ,kBACjB,QAAQ,eAAe"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { wrapOpenAIClientError } from "../utils/client.js";
|
|
2
|
+
import { toDecisionInput } from "./input.js";
|
|
3
|
+
import { convertResponsesUsageToUsageMetadata } from "../converters/responses.js";
|
|
4
|
+
import { toQuestionParam } from "./types.js";
|
|
5
|
+
import { OpenAI } from "openai";
|
|
6
|
+
import { getEnvironmentVariable } from "@langchain/core/utils/env";
|
|
7
|
+
import { resolveLangSmithGatewayConfig } from "@langchain/core/utils/gateway";
|
|
8
|
+
import { Runnable } from "@langchain/core/runnables";
|
|
9
|
+
// src/decisions/index.ts
|
|
10
|
+
/**
|
|
11
|
+
* Ask typed questions about text, messages or JSON state with the OpenAI Decisions
|
|
12
|
+
* API (beta). Answer types are inferred from the questions passed to `invoke`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const decisions = new OpenAIDecisions({ model: "gpt-6-luna" });
|
|
17
|
+
* const { answers } = await decisions.invoke({
|
|
18
|
+
* input: "I was charged twice!",
|
|
19
|
+
* questions: {
|
|
20
|
+
* urgent: { type: "predicate", instructions: "Is this urgent?" },
|
|
21
|
+
* team: {
|
|
22
|
+
* type: "choice",
|
|
23
|
+
* instructions: "Which team should handle this?",
|
|
24
|
+
* choices: { billing: "Payments", technical: null },
|
|
25
|
+
* },
|
|
26
|
+
* },
|
|
27
|
+
* });
|
|
28
|
+
* if (answers.team.type === "choice") answers.team.choice; // "billing" | "technical"
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
var OpenAIDecisions = class extends Runnable {
|
|
32
|
+
static lc_name() {
|
|
33
|
+
return "OpenAIDecisions";
|
|
34
|
+
}
|
|
35
|
+
lc_namespace = [
|
|
36
|
+
"langchain",
|
|
37
|
+
"openai",
|
|
38
|
+
"decisions"
|
|
39
|
+
];
|
|
40
|
+
model;
|
|
41
|
+
client;
|
|
42
|
+
constructor(modelOrFields, fieldsArg) {
|
|
43
|
+
const fields = typeof modelOrFields === "string" ? {
|
|
44
|
+
...fieldsArg,
|
|
45
|
+
model: modelOrFields
|
|
46
|
+
} : modelOrFields;
|
|
47
|
+
const { apiKey, ...kwargs } = fields;
|
|
48
|
+
super(kwargs);
|
|
49
|
+
if (!fields.model?.trim()) throw new Error("An OpenAI Decisions model is required.");
|
|
50
|
+
this.model = fields.model;
|
|
51
|
+
const gateway = resolveLangSmithGatewayConfig({
|
|
52
|
+
baseURL: fields.configuration?.baseURL ?? (getEnvironmentVariable("OPENAI_API_BASE") || getEnvironmentVariable("OPENAI_BASE_URL") || void 0),
|
|
53
|
+
providerPath: "openai/v1"
|
|
54
|
+
});
|
|
55
|
+
this.client = new OpenAI({
|
|
56
|
+
...fields.configuration,
|
|
57
|
+
baseURL: gateway.baseURL,
|
|
58
|
+
apiKey: apiKey ?? gateway.apiKey ?? getEnvironmentVariable("OPENAI_API_KEY")
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
async invoke(request, options) {
|
|
62
|
+
return this._callWithConfig(async ({ input, questions }, config) => {
|
|
63
|
+
const names = Object.keys(questions);
|
|
64
|
+
if (!names.length) throw new Error("OpenAI Decisions requires at least one question.");
|
|
65
|
+
let decision;
|
|
66
|
+
let response;
|
|
67
|
+
try {
|
|
68
|
+
({data: decision, response} = await this.client.decisions.create({
|
|
69
|
+
model: this.model,
|
|
70
|
+
input: toDecisionInput(input),
|
|
71
|
+
questions: names.map((name) => toQuestionParam(name, questions[name]))
|
|
72
|
+
}, { signal: config?.signal }).withResponse());
|
|
73
|
+
} catch (error) {
|
|
74
|
+
throw wrapOpenAIClientError(error);
|
|
75
|
+
}
|
|
76
|
+
const answers = new Map(decision.answers.map(({ name, ...answer }) => [name, answer]));
|
|
77
|
+
for (const name of names) if (!answers.has(name)) throw new Error(`OpenAI Decisions returned no answer for question "${name}".`);
|
|
78
|
+
return {
|
|
79
|
+
answers: Object.fromEntries(answers),
|
|
80
|
+
model: decision.model,
|
|
81
|
+
requestId: response.headers.get("x-request-id") ?? void 0,
|
|
82
|
+
usage_metadata: convertResponsesUsageToUsageMetadata(decision.usage)
|
|
83
|
+
};
|
|
84
|
+
}, request, {
|
|
85
|
+
...options,
|
|
86
|
+
runType: "llm",
|
|
87
|
+
metadata: {
|
|
88
|
+
...options?.metadata,
|
|
89
|
+
ls_provider: "openai",
|
|
90
|
+
ls_model_name: this.model,
|
|
91
|
+
ls_model_type: "chat"
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
export { OpenAIDecisions };
|
|
97
|
+
|
|
98
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["OpenAIClient"],"sources":["../../src/decisions/index.ts"],"sourcesContent":["import { OpenAI as OpenAIClient, type ClientOptions } from \"openai\";\nimport { Runnable, type RunnableConfig } from \"@langchain/core/runnables\";\nimport { getEnvironmentVariable } from \"@langchain/core/utils/env\";\nimport { resolveLangSmithGatewayConfig } from \"@langchain/core/utils/gateway\";\nimport { wrapOpenAIClientError } from \"../utils/client.js\";\nimport { toDecisionInput } from \"./input.js\";\nimport { convertResponsesUsageToUsageMetadata } from \"../converters/responses.js\";\nimport {\n toQuestionParam,\n type Answers,\n type DecisionRequest,\n type DecisionResult,\n type Questions,\n} from \"./types.js\";\n\nexport type {\n Answer,\n AnswerFor,\n Answers,\n Choice,\n ChoiceAnswer,\n DecisionInput,\n DecisionRequest,\n DecisionResult,\n Level,\n Predicate,\n PredicateAnswer,\n Question,\n Questions,\n RefusalAnswer,\n Score,\n ScoreAnswer,\n} from \"./types.js\";\n\nexport interface OpenAIDecisionsFields {\n /** Decisions model name, such as `gpt-6-luna`. */\n model: string;\n /**\n * Falls back to the LangSmith gateway key when routing through the gateway, then\n * to the `OPENAI_API_KEY` environment variable.\n */\n apiKey?: string;\n /**\n * OpenAI SDK client options, such as `baseURL`, `timeout` or `fetch`. Without a\n * `baseURL`, `OPENAI_API_BASE` or `OPENAI_BASE_URL`, setting `LANGSMITH_GATEWAY`\n * routes requests through the LangSmith gateway, as with `ChatOpenAI`.\n */\n configuration?: Omit<ClientOptions, \"apiKey\">;\n}\n\n/**\n * Ask typed questions about text, messages or JSON state with the OpenAI Decisions\n * API (beta). Answer types are inferred from the questions passed to `invoke`.\n *\n * @example\n * ```ts\n * const decisions = new OpenAIDecisions({ model: \"gpt-6-luna\" });\n * const { answers } = await decisions.invoke({\n * input: \"I was charged twice!\",\n * questions: {\n * urgent: { type: \"predicate\", instructions: \"Is this urgent?\" },\n * team: {\n * type: \"choice\",\n * instructions: \"Which team should handle this?\",\n * choices: { billing: \"Payments\", technical: null },\n * },\n * },\n * });\n * if (answers.team.type === \"choice\") answers.team.choice; // \"billing\" | \"technical\"\n * ```\n */\nexport class OpenAIDecisions extends Runnable<DecisionRequest, DecisionResult> {\n static lc_name() {\n return \"OpenAIDecisions\";\n }\n\n lc_namespace = [\"langchain\", \"openai\", \"decisions\"];\n\n readonly model: string;\n\n protected client: OpenAIClient;\n\n constructor(model: string, fields?: Omit<OpenAIDecisionsFields, \"model\">);\n constructor(fields: OpenAIDecisionsFields);\n constructor(\n modelOrFields: string | OpenAIDecisionsFields,\n fieldsArg?: Omit<OpenAIDecisionsFields, \"model\">\n ) {\n const fields =\n typeof modelOrFields === \"string\"\n ? { ...fieldsArg, model: modelOrFields }\n : modelOrFields;\n const { apiKey, ...kwargs } = fields;\n super(kwargs);\n if (!fields.model?.trim())\n throw new Error(\"An OpenAI Decisions model is required.\");\n this.model = fields.model;\n const gateway = resolveLangSmithGatewayConfig({\n baseURL:\n fields.configuration?.baseURL ??\n (getEnvironmentVariable(\"OPENAI_API_BASE\") ||\n getEnvironmentVariable(\"OPENAI_BASE_URL\") ||\n undefined),\n providerPath: \"openai/v1\",\n });\n this.client = new OpenAIClient({\n ...fields.configuration,\n baseURL: gateway.baseURL,\n apiKey:\n apiKey ?? gateway.apiKey ?? getEnvironmentVariable(\"OPENAI_API_KEY\"),\n });\n }\n\n async invoke<const Q extends Questions>(\n request: DecisionRequest<Q>,\n options?: Partial<RunnableConfig>\n ): Promise<DecisionResult<Q>> {\n return this._callWithConfig(\n async (\n { input, questions }: DecisionRequest<Q>,\n config?: Partial<RunnableConfig>\n ): Promise<DecisionResult<Q>> => {\n const names = Object.keys(questions);\n if (!names.length)\n throw new Error(\"OpenAI Decisions requires at least one question.\");\n let decision: OpenAIClient.Decision;\n let response: Response;\n try {\n ({ data: decision, response } = await this.client.decisions\n .create(\n {\n model: this.model,\n input: toDecisionInput(input),\n questions: names.map((name) =>\n toQuestionParam(name, questions[name])\n ),\n },\n { signal: config?.signal }\n )\n .withResponse());\n } catch (error) {\n throw wrapOpenAIClientError(error);\n }\n const answers = new Map(\n decision.answers.map(({ name, ...answer }) => [name, answer])\n );\n for (const name of names)\n if (!answers.has(name))\n throw new Error(\n `OpenAI Decisions returned no answer for question \"${name}\".`\n );\n return {\n answers: Object.fromEntries(answers) as Answers<Q>,\n model: decision.model,\n requestId: response.headers.get(\"x-request-id\") ?? undefined,\n usage_metadata: convertResponsesUsageToUsageMetadata(decision.usage),\n };\n },\n request,\n {\n ...options,\n runType: \"llm\",\n metadata: {\n ...options?.metadata,\n ls_provider: \"openai\",\n ls_model_name: this.model,\n ls_model_type: \"chat\",\n },\n }\n ) as Promise<DecisionResult<Q>>;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuEA,IAAa,kBAAb,cAAqC,SAA0C;CAC7E,OAAO,UAAU;EACf,OAAO;CACT;CAEA,eAAe;EAAC;EAAa;EAAU;CAAW;CAElD;CAEA;CAIA,YACE,eACA,WACA;EACA,MAAM,SACJ,OAAO,kBAAkB,WACrB;GAAE,GAAG;GAAW,OAAO;EAAc,IACrC;EACN,MAAM,EAAE,QAAQ,GAAG,WAAW;EAC9B,MAAM,MAAM;EACZ,IAAI,CAAC,OAAO,OAAO,KAAK,GACtB,MAAM,IAAI,MAAM,wCAAwC;EAC1D,KAAK,QAAQ,OAAO;EACpB,MAAM,UAAU,8BAA8B;GAC5C,SACE,OAAO,eAAe,YACrB,uBAAuB,iBAAiB,KACvC,uBAAuB,iBAAiB,KACxC,KAAA;GACJ,cAAc;EAChB,CAAC;EACD,KAAK,SAAS,IAAIA,OAAa;GAC7B,GAAG,OAAO;GACV,SAAS,QAAQ;GACjB,QACE,UAAU,QAAQ,UAAU,uBAAuB,gBAAgB;EACvE,CAAC;CACH;CAEA,MAAM,OACJ,SACA,SAC4B;EAC5B,OAAO,KAAK,gBACV,OACE,EAAE,OAAO,aACT,WAC+B;GAC/B,MAAM,QAAQ,OAAO,KAAK,SAAS;GACnC,IAAI,CAAC,MAAM,QACT,MAAM,IAAI,MAAM,kDAAkD;GACpE,IAAI;GACJ,IAAI;GACJ,IAAI;IACF,CAAC,CAAE,MAAM,UAAU,YAAa,MAAM,KAAK,OAAO,UAC/C,OACC;KACE,OAAO,KAAK;KACZ,OAAO,gBAAgB,KAAK;KAC5B,WAAW,MAAM,KAAK,SACpB,gBAAgB,MAAM,UAAU,KAAK,CACvC;IACF,GACA,EAAE,QAAQ,QAAQ,OAAO,CAC3B,CAAC,CACA,aAAa;GAClB,SAAS,OAAO;IACd,MAAM,sBAAsB,KAAK;GACnC;GACA,MAAM,UAAU,IAAI,IAClB,SAAS,QAAQ,KAAK,EAAE,MAAM,GAAG,aAAa,CAAC,MAAM,MAAM,CAAC,CAC9D;GACA,KAAK,MAAM,QAAQ,OACjB,IAAI,CAAC,QAAQ,IAAI,IAAI,GACnB,MAAM,IAAI,MACR,qDAAqD,KAAK,GAC5D;GACJ,OAAO;IACL,SAAS,OAAO,YAAY,OAAO;IACnC,OAAO,SAAS;IAChB,WAAW,SAAS,QAAQ,IAAI,cAAc,KAAK,KAAA;IACnD,gBAAgB,qCAAqC,SAAS,KAAK;GACrE;EACF,GACA,SACA;GACE,GAAG;GACH,SAAS;GACT,UAAU;IACR,GAAG,SAAS;IACZ,aAAa;IACb,eAAe,KAAK;IACpB,eAAe;GACjB;EACF,CACF;CACF;AACF"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
const require_responses = require("../converters/responses.cjs");
|
|
2
|
+
let _langchain_core_messages = require("@langchain/core/messages");
|
|
3
|
+
// src/decisions/input.ts
|
|
4
|
+
/**
|
|
5
|
+
* Keeps text and image parts, which is all user messages and tool outputs accept,
|
|
6
|
+
* and replaces anything else, such as `input_file`, with a placeholder.
|
|
7
|
+
*/
|
|
8
|
+
function toInputParts(content) {
|
|
9
|
+
return content.map((part) => part.type === "input_text" && typeof part.text === "string" ? {
|
|
10
|
+
type: "input_text",
|
|
11
|
+
text: part.text
|
|
12
|
+
} : part.type === "input_image" && typeof part.image_url === "string" ? {
|
|
13
|
+
type: "input_image",
|
|
14
|
+
image_url: part.image_url
|
|
15
|
+
} : {
|
|
16
|
+
type: "input_text",
|
|
17
|
+
text: `[${part.type} omitted]`
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** System and developer messages accept only text parts. */
|
|
21
|
+
function toTextParts(content) {
|
|
22
|
+
return toInputParts(content).map((part) => part.type === "input_text" ? part : {
|
|
23
|
+
type: "input_text",
|
|
24
|
+
text: "[input_image omitted]"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Assistant messages accept `output_text` and `refusal` parts, without `annotations`. */
|
|
28
|
+
function toAssistantParts(content) {
|
|
29
|
+
return content.flatMap((part) => {
|
|
30
|
+
if (part.type === "output_text" && typeof part.text === "string") return [{
|
|
31
|
+
type: "output_text",
|
|
32
|
+
text: part.text
|
|
33
|
+
}];
|
|
34
|
+
if (part.type === "refusal" && typeof part.refusal === "string") return [{
|
|
35
|
+
type: "refusal",
|
|
36
|
+
refusal: part.refusal
|
|
37
|
+
}];
|
|
38
|
+
return [];
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Rebuilds one Responses item with only the fields the Decisions API accepts.
|
|
43
|
+
* Items it has no equivalent for, such as reasoning, are dropped.
|
|
44
|
+
*/
|
|
45
|
+
function toDecisionItem(item) {
|
|
46
|
+
if ("role" in item && (!("type" in item) || item.type === "message")) {
|
|
47
|
+
const { role, content } = item;
|
|
48
|
+
if (typeof content === "string") return role === "user" || role === "system" || role === "developer" || role === "assistant" ? [{
|
|
49
|
+
role,
|
|
50
|
+
content
|
|
51
|
+
}] : [];
|
|
52
|
+
if (role === "user") return [{
|
|
53
|
+
role,
|
|
54
|
+
content: toInputParts(content)
|
|
55
|
+
}];
|
|
56
|
+
if (role === "system" || role === "developer") return [{
|
|
57
|
+
role,
|
|
58
|
+
content: toTextParts(content)
|
|
59
|
+
}];
|
|
60
|
+
if (role === "assistant") return [{
|
|
61
|
+
role,
|
|
62
|
+
content: toAssistantParts(content)
|
|
63
|
+
}];
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
if (!("type" in item)) return [];
|
|
67
|
+
switch (item.type) {
|
|
68
|
+
case "function_call": return [{
|
|
69
|
+
type: item.type,
|
|
70
|
+
call_id: item.call_id,
|
|
71
|
+
name: item.name,
|
|
72
|
+
arguments: item.arguments
|
|
73
|
+
}];
|
|
74
|
+
case "custom_tool_call": return [{
|
|
75
|
+
type: item.type,
|
|
76
|
+
call_id: item.call_id,
|
|
77
|
+
name: item.name,
|
|
78
|
+
input: item.input
|
|
79
|
+
}];
|
|
80
|
+
case "function_call_output":
|
|
81
|
+
case "custom_tool_call_output": return [{
|
|
82
|
+
type: item.type,
|
|
83
|
+
call_id: item.call_id ?? "",
|
|
84
|
+
output: typeof item.output === "string" ? item.output : toInputParts(item.output)
|
|
85
|
+
}];
|
|
86
|
+
default: return [];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Converts LangChain messages to Decisions input items. */
|
|
90
|
+
function toDecisionItems(messages) {
|
|
91
|
+
return require_responses.convertMessagesToResponsesInput({
|
|
92
|
+
messages,
|
|
93
|
+
zdrEnabled: true,
|
|
94
|
+
model: ""
|
|
95
|
+
}).flatMap(toDecisionItem);
|
|
96
|
+
}
|
|
97
|
+
/** Replaces messages nested in JSON state with their Decisions input items. */
|
|
98
|
+
function toJSONValue(value) {
|
|
99
|
+
if (_langchain_core_messages.BaseMessage.isInstance(value)) return toDecisionItems([value]);
|
|
100
|
+
if (Array.isArray(value)) return value.flatMap((item) => _langchain_core_messages.BaseMessage.isInstance(item) ? toDecisionItems([item]) : [toJSONValue(item)]);
|
|
101
|
+
if (typeof value === "object" && value?.constructor === Object) return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, toJSONValue(item)]));
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Converts input to the Decisions API `input` field: strings as they are, messages
|
|
106
|
+
* as a native conversation, and anything else as an `input_json` part.
|
|
107
|
+
*/
|
|
108
|
+
function toDecisionInput(input) {
|
|
109
|
+
if (typeof input === "string") return input;
|
|
110
|
+
const values = Array.isArray(input) ? input : [input];
|
|
111
|
+
if (values.length > 0 && values.every((value) => _langchain_core_messages.BaseMessage.isInstance(value))) return toDecisionItems(values);
|
|
112
|
+
return [{
|
|
113
|
+
role: "user",
|
|
114
|
+
content: [{
|
|
115
|
+
type: "input_json",
|
|
116
|
+
data: toJSONValue(input)
|
|
117
|
+
}]
|
|
118
|
+
}];
|
|
119
|
+
}
|
|
120
|
+
exports.toDecisionInput = toDecisionInput;
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=input.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.cjs","names":["convertMessagesToResponsesInput","BaseMessage"],"sources":["../../src/decisions/input.ts"],"sourcesContent":["import type { OpenAI as OpenAIClient } from \"openai\";\nimport { BaseMessage } from \"@langchain/core/messages\";\nimport { convertMessagesToResponsesInput } from \"../converters/responses.js\";\nimport type { DecisionInput } from \"./types.js\";\n\n/**\n * How LangChain input becomes the Decisions API `input` field.\n *\n * The Decisions API accepts a string, or a list of items using a subset of the\n * Responses API input format: `user`, `system`, `developer` and `assistant` messages,\n * plus function and custom tool calls and their outputs. Rather than writing a second\n * LangChain message converter, messages go through the Responses converter\n * (`convertMessagesToResponsesInput`), which already handles roles, content blocks,\n * tool calls and tool results. The Decisions API is strict about what it accepts,\n * though, and Responses items carry things it rejects: reasoning items, item `id`s,\n * `annotations` and `phase` on assistant text, and content parts such as\n * `input_file`. So each Responses item is rebuilt with only the fields the Decisions\n * API accepts (`toDecisionItem`), and unsupported content parts are replaced by a\n * text placeholder so the model knows something was there.\n *\n * Input that is not messages, such as application state, is sent as an `input_json`\n * part, which the API reads as structured data. Messages nested in that state are\n * converted to the same items, because a `BaseMessage` instance would otherwise be\n * serialized as LangChain's internal constructor format.\n */\n\ntype ResponsesItem = ReturnType<typeof convertMessagesToResponsesInput>[number];\ntype DecisionItem = Exclude<\n OpenAIClient.DecisionCreateParams[\"input\"],\n string\n>[number];\ntype InputPart =\n | OpenAIClient.DecisionInputText\n | OpenAIClient.DecisionInputImage;\ntype AssistantPart = Exclude<\n OpenAIClient.DecisionInputMessage.DecisionInputAssistantMessage[\"content\"],\n string\n>[number];\n\n/** A Responses content part, loosely typed because roles and tool outputs use different part unions. */\ntype ResponsesPart = {\n type: string;\n text?: unknown;\n image_url?: unknown;\n refusal?: unknown;\n};\n\n/**\n * Keeps text and image parts, which is all user messages and tool outputs accept,\n * and replaces anything else, such as `input_file`, with a placeholder.\n */\nfunction toInputParts(content: unknown): InputPart[] {\n return (content as ResponsesPart[]).map((part) =>\n part.type === \"input_text\" && typeof part.text === \"string\"\n ? { type: \"input_text\", text: part.text }\n : part.type === \"input_image\" && typeof part.image_url === \"string\"\n ? { type: \"input_image\", image_url: part.image_url }\n : { type: \"input_text\", text: `[${part.type} omitted]` }\n );\n}\n\n/** System and developer messages accept only text parts. */\nfunction toTextParts(content: unknown): OpenAIClient.DecisionInputText[] {\n return toInputParts(content).map((part) =>\n part.type === \"input_text\"\n ? part\n : { type: \"input_text\", text: \"[input_image omitted]\" }\n );\n}\n\n/** Assistant messages accept `output_text` and `refusal` parts, without `annotations`. */\nfunction toAssistantParts(content: unknown): AssistantPart[] {\n return (content as ResponsesPart[]).flatMap((part): AssistantPart[] => {\n if (part.type === \"output_text\" && typeof part.text === \"string\")\n return [{ type: \"output_text\", text: part.text }];\n if (part.type === \"refusal\" && typeof part.refusal === \"string\")\n return [{ type: \"refusal\", refusal: part.refusal }];\n return [];\n });\n}\n\n/**\n * Rebuilds one Responses item with only the fields the Decisions API accepts.\n * Items it has no equivalent for, such as reasoning, are dropped.\n */\nfunction toDecisionItem(item: ResponsesItem): DecisionItem[] {\n if (\"role\" in item && (!(\"type\" in item) || item.type === \"message\")) {\n const { role, content } = item;\n if (typeof content === \"string\")\n return role === \"user\" ||\n role === \"system\" ||\n role === \"developer\" ||\n role === \"assistant\"\n ? [{ role, content }]\n : [];\n if (role === \"user\") return [{ role, content: toInputParts(content) }];\n if (role === \"system\" || role === \"developer\")\n return [{ role, content: toTextParts(content) }];\n if (role === \"assistant\")\n return [{ role, content: toAssistantParts(content) }];\n return [];\n }\n if (!(\"type\" in item)) return [];\n switch (item.type) {\n case \"function_call\":\n return [\n {\n type: item.type,\n call_id: item.call_id,\n name: item.name,\n arguments: item.arguments,\n },\n ];\n case \"custom_tool_call\":\n return [\n {\n type: item.type,\n call_id: item.call_id,\n name: item.name,\n input: item.input,\n },\n ];\n case \"function_call_output\":\n case \"custom_tool_call_output\":\n return [\n {\n type: item.type,\n call_id: item.call_id ?? \"\",\n output:\n typeof item.output === \"string\"\n ? item.output\n : toInputParts(item.output),\n },\n ];\n default:\n return [];\n }\n}\n\n/** Converts LangChain messages to Decisions input items. */\nfunction toDecisionItems(messages: BaseMessage[]): DecisionItem[] {\n return convertMessagesToResponsesInput({\n messages,\n zdrEnabled: true,\n model: \"\",\n }).flatMap(toDecisionItem);\n}\n\n/** Replaces messages nested in JSON state with their Decisions input items. */\nfunction toJSONValue(value: unknown): unknown {\n if (BaseMessage.isInstance(value)) return toDecisionItems([value]);\n if (Array.isArray(value))\n return value.flatMap((item) =>\n BaseMessage.isInstance(item)\n ? toDecisionItems([item])\n : [toJSONValue(item)]\n );\n if (typeof value === \"object\" && value?.constructor === Object)\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, toJSONValue(item)])\n );\n return value;\n}\n\n/**\n * Converts input to the Decisions API `input` field: strings as they are, messages\n * as a native conversation, and anything else as an `input_json` part.\n */\nexport function toDecisionInput(\n input: DecisionInput\n): OpenAIClient.DecisionCreateParams[\"input\"] {\n if (typeof input === \"string\") return input;\n const values = Array.isArray(input) ? input : [input];\n if (\n values.length > 0 &&\n values.every((value) => BaseMessage.isInstance(value))\n )\n return toDecisionItems(values);\n return [\n {\n role: \"user\",\n content: [\n {\n type: \"input_json\",\n data: toJSONValue(input) as OpenAIClient.DecisionInputJSON[\"data\"],\n },\n ],\n },\n ];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { convertMessagesToResponsesInput } from "../converters/responses.js";
|
|
2
|
+
import { BaseMessage } from "@langchain/core/messages";
|
|
3
|
+
// src/decisions/input.ts
|
|
4
|
+
/**
|
|
5
|
+
* Keeps text and image parts, which is all user messages and tool outputs accept,
|
|
6
|
+
* and replaces anything else, such as `input_file`, with a placeholder.
|
|
7
|
+
*/
|
|
8
|
+
function toInputParts(content) {
|
|
9
|
+
return content.map((part) => part.type === "input_text" && typeof part.text === "string" ? {
|
|
10
|
+
type: "input_text",
|
|
11
|
+
text: part.text
|
|
12
|
+
} : part.type === "input_image" && typeof part.image_url === "string" ? {
|
|
13
|
+
type: "input_image",
|
|
14
|
+
image_url: part.image_url
|
|
15
|
+
} : {
|
|
16
|
+
type: "input_text",
|
|
17
|
+
text: `[${part.type} omitted]`
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** System and developer messages accept only text parts. */
|
|
21
|
+
function toTextParts(content) {
|
|
22
|
+
return toInputParts(content).map((part) => part.type === "input_text" ? part : {
|
|
23
|
+
type: "input_text",
|
|
24
|
+
text: "[input_image omitted]"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Assistant messages accept `output_text` and `refusal` parts, without `annotations`. */
|
|
28
|
+
function toAssistantParts(content) {
|
|
29
|
+
return content.flatMap((part) => {
|
|
30
|
+
if (part.type === "output_text" && typeof part.text === "string") return [{
|
|
31
|
+
type: "output_text",
|
|
32
|
+
text: part.text
|
|
33
|
+
}];
|
|
34
|
+
if (part.type === "refusal" && typeof part.refusal === "string") return [{
|
|
35
|
+
type: "refusal",
|
|
36
|
+
refusal: part.refusal
|
|
37
|
+
}];
|
|
38
|
+
return [];
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Rebuilds one Responses item with only the fields the Decisions API accepts.
|
|
43
|
+
* Items it has no equivalent for, such as reasoning, are dropped.
|
|
44
|
+
*/
|
|
45
|
+
function toDecisionItem(item) {
|
|
46
|
+
if ("role" in item && (!("type" in item) || item.type === "message")) {
|
|
47
|
+
const { role, content } = item;
|
|
48
|
+
if (typeof content === "string") return role === "user" || role === "system" || role === "developer" || role === "assistant" ? [{
|
|
49
|
+
role,
|
|
50
|
+
content
|
|
51
|
+
}] : [];
|
|
52
|
+
if (role === "user") return [{
|
|
53
|
+
role,
|
|
54
|
+
content: toInputParts(content)
|
|
55
|
+
}];
|
|
56
|
+
if (role === "system" || role === "developer") return [{
|
|
57
|
+
role,
|
|
58
|
+
content: toTextParts(content)
|
|
59
|
+
}];
|
|
60
|
+
if (role === "assistant") return [{
|
|
61
|
+
role,
|
|
62
|
+
content: toAssistantParts(content)
|
|
63
|
+
}];
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
if (!("type" in item)) return [];
|
|
67
|
+
switch (item.type) {
|
|
68
|
+
case "function_call": return [{
|
|
69
|
+
type: item.type,
|
|
70
|
+
call_id: item.call_id,
|
|
71
|
+
name: item.name,
|
|
72
|
+
arguments: item.arguments
|
|
73
|
+
}];
|
|
74
|
+
case "custom_tool_call": return [{
|
|
75
|
+
type: item.type,
|
|
76
|
+
call_id: item.call_id,
|
|
77
|
+
name: item.name,
|
|
78
|
+
input: item.input
|
|
79
|
+
}];
|
|
80
|
+
case "function_call_output":
|
|
81
|
+
case "custom_tool_call_output": return [{
|
|
82
|
+
type: item.type,
|
|
83
|
+
call_id: item.call_id ?? "",
|
|
84
|
+
output: typeof item.output === "string" ? item.output : toInputParts(item.output)
|
|
85
|
+
}];
|
|
86
|
+
default: return [];
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** Converts LangChain messages to Decisions input items. */
|
|
90
|
+
function toDecisionItems(messages) {
|
|
91
|
+
return convertMessagesToResponsesInput({
|
|
92
|
+
messages,
|
|
93
|
+
zdrEnabled: true,
|
|
94
|
+
model: ""
|
|
95
|
+
}).flatMap(toDecisionItem);
|
|
96
|
+
}
|
|
97
|
+
/** Replaces messages nested in JSON state with their Decisions input items. */
|
|
98
|
+
function toJSONValue(value) {
|
|
99
|
+
if (BaseMessage.isInstance(value)) return toDecisionItems([value]);
|
|
100
|
+
if (Array.isArray(value)) return value.flatMap((item) => BaseMessage.isInstance(item) ? toDecisionItems([item]) : [toJSONValue(item)]);
|
|
101
|
+
if (typeof value === "object" && value?.constructor === Object) return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, toJSONValue(item)]));
|
|
102
|
+
return value;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Converts input to the Decisions API `input` field: strings as they are, messages
|
|
106
|
+
* as a native conversation, and anything else as an `input_json` part.
|
|
107
|
+
*/
|
|
108
|
+
function toDecisionInput(input) {
|
|
109
|
+
if (typeof input === "string") return input;
|
|
110
|
+
const values = Array.isArray(input) ? input : [input];
|
|
111
|
+
if (values.length > 0 && values.every((value) => BaseMessage.isInstance(value))) return toDecisionItems(values);
|
|
112
|
+
return [{
|
|
113
|
+
role: "user",
|
|
114
|
+
content: [{
|
|
115
|
+
type: "input_json",
|
|
116
|
+
data: toJSONValue(input)
|
|
117
|
+
}]
|
|
118
|
+
}];
|
|
119
|
+
}
|
|
120
|
+
export { toDecisionInput };
|
|
121
|
+
|
|
122
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","names":[],"sources":["../../src/decisions/input.ts"],"sourcesContent":["import type { OpenAI as OpenAIClient } from \"openai\";\nimport { BaseMessage } from \"@langchain/core/messages\";\nimport { convertMessagesToResponsesInput } from \"../converters/responses.js\";\nimport type { DecisionInput } from \"./types.js\";\n\n/**\n * How LangChain input becomes the Decisions API `input` field.\n *\n * The Decisions API accepts a string, or a list of items using a subset of the\n * Responses API input format: `user`, `system`, `developer` and `assistant` messages,\n * plus function and custom tool calls and their outputs. Rather than writing a second\n * LangChain message converter, messages go through the Responses converter\n * (`convertMessagesToResponsesInput`), which already handles roles, content blocks,\n * tool calls and tool results. The Decisions API is strict about what it accepts,\n * though, and Responses items carry things it rejects: reasoning items, item `id`s,\n * `annotations` and `phase` on assistant text, and content parts such as\n * `input_file`. So each Responses item is rebuilt with only the fields the Decisions\n * API accepts (`toDecisionItem`), and unsupported content parts are replaced by a\n * text placeholder so the model knows something was there.\n *\n * Input that is not messages, such as application state, is sent as an `input_json`\n * part, which the API reads as structured data. Messages nested in that state are\n * converted to the same items, because a `BaseMessage` instance would otherwise be\n * serialized as LangChain's internal constructor format.\n */\n\ntype ResponsesItem = ReturnType<typeof convertMessagesToResponsesInput>[number];\ntype DecisionItem = Exclude<\n OpenAIClient.DecisionCreateParams[\"input\"],\n string\n>[number];\ntype InputPart =\n | OpenAIClient.DecisionInputText\n | OpenAIClient.DecisionInputImage;\ntype AssistantPart = Exclude<\n OpenAIClient.DecisionInputMessage.DecisionInputAssistantMessage[\"content\"],\n string\n>[number];\n\n/** A Responses content part, loosely typed because roles and tool outputs use different part unions. */\ntype ResponsesPart = {\n type: string;\n text?: unknown;\n image_url?: unknown;\n refusal?: unknown;\n};\n\n/**\n * Keeps text and image parts, which is all user messages and tool outputs accept,\n * and replaces anything else, such as `input_file`, with a placeholder.\n */\nfunction toInputParts(content: unknown): InputPart[] {\n return (content as ResponsesPart[]).map((part) =>\n part.type === \"input_text\" && typeof part.text === \"string\"\n ? { type: \"input_text\", text: part.text }\n : part.type === \"input_image\" && typeof part.image_url === \"string\"\n ? { type: \"input_image\", image_url: part.image_url }\n : { type: \"input_text\", text: `[${part.type} omitted]` }\n );\n}\n\n/** System and developer messages accept only text parts. */\nfunction toTextParts(content: unknown): OpenAIClient.DecisionInputText[] {\n return toInputParts(content).map((part) =>\n part.type === \"input_text\"\n ? part\n : { type: \"input_text\", text: \"[input_image omitted]\" }\n );\n}\n\n/** Assistant messages accept `output_text` and `refusal` parts, without `annotations`. */\nfunction toAssistantParts(content: unknown): AssistantPart[] {\n return (content as ResponsesPart[]).flatMap((part): AssistantPart[] => {\n if (part.type === \"output_text\" && typeof part.text === \"string\")\n return [{ type: \"output_text\", text: part.text }];\n if (part.type === \"refusal\" && typeof part.refusal === \"string\")\n return [{ type: \"refusal\", refusal: part.refusal }];\n return [];\n });\n}\n\n/**\n * Rebuilds one Responses item with only the fields the Decisions API accepts.\n * Items it has no equivalent for, such as reasoning, are dropped.\n */\nfunction toDecisionItem(item: ResponsesItem): DecisionItem[] {\n if (\"role\" in item && (!(\"type\" in item) || item.type === \"message\")) {\n const { role, content } = item;\n if (typeof content === \"string\")\n return role === \"user\" ||\n role === \"system\" ||\n role === \"developer\" ||\n role === \"assistant\"\n ? [{ role, content }]\n : [];\n if (role === \"user\") return [{ role, content: toInputParts(content) }];\n if (role === \"system\" || role === \"developer\")\n return [{ role, content: toTextParts(content) }];\n if (role === \"assistant\")\n return [{ role, content: toAssistantParts(content) }];\n return [];\n }\n if (!(\"type\" in item)) return [];\n switch (item.type) {\n case \"function_call\":\n return [\n {\n type: item.type,\n call_id: item.call_id,\n name: item.name,\n arguments: item.arguments,\n },\n ];\n case \"custom_tool_call\":\n return [\n {\n type: item.type,\n call_id: item.call_id,\n name: item.name,\n input: item.input,\n },\n ];\n case \"function_call_output\":\n case \"custom_tool_call_output\":\n return [\n {\n type: item.type,\n call_id: item.call_id ?? \"\",\n output:\n typeof item.output === \"string\"\n ? item.output\n : toInputParts(item.output),\n },\n ];\n default:\n return [];\n }\n}\n\n/** Converts LangChain messages to Decisions input items. */\nfunction toDecisionItems(messages: BaseMessage[]): DecisionItem[] {\n return convertMessagesToResponsesInput({\n messages,\n zdrEnabled: true,\n model: \"\",\n }).flatMap(toDecisionItem);\n}\n\n/** Replaces messages nested in JSON state with their Decisions input items. */\nfunction toJSONValue(value: unknown): unknown {\n if (BaseMessage.isInstance(value)) return toDecisionItems([value]);\n if (Array.isArray(value))\n return value.flatMap((item) =>\n BaseMessage.isInstance(item)\n ? toDecisionItems([item])\n : [toJSONValue(item)]\n );\n if (typeof value === \"object\" && value?.constructor === Object)\n return Object.fromEntries(\n Object.entries(value).map(([key, item]) => [key, toJSONValue(item)])\n );\n return value;\n}\n\n/**\n * Converts input to the Decisions API `input` field: strings as they are, messages\n * as a native conversation, and anything else as an `input_json` part.\n */\nexport function toDecisionInput(\n input: DecisionInput\n): OpenAIClient.DecisionCreateParams[\"input\"] {\n if (typeof input === \"string\") return input;\n const values = Array.isArray(input) ? input : [input];\n if (\n values.length > 0 &&\n values.every((value) => BaseMessage.isInstance(value))\n )\n return toDecisionItems(values);\n return [\n {\n role: \"user\",\n content: [\n {\n type: \"input_json\",\n data: toJSONValue(input) as OpenAIClient.DecisionInputJSON[\"data\"],\n },\n ],\n },\n ];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// src/decisions/types.ts
|
|
2
|
+
/** Converts a named question to the shape the Decisions API expects. */
|
|
3
|
+
function toQuestionParam(name, question) {
|
|
4
|
+
const { type, instructions } = question;
|
|
5
|
+
if (type === "predicate") return {
|
|
6
|
+
type,
|
|
7
|
+
name,
|
|
8
|
+
instructions
|
|
9
|
+
};
|
|
10
|
+
if (type === "choice") return {
|
|
11
|
+
type,
|
|
12
|
+
name,
|
|
13
|
+
instructions,
|
|
14
|
+
choices: Object.entries(question.choices).map(([value, description]) => description == null ? { value } : {
|
|
15
|
+
value,
|
|
16
|
+
description
|
|
17
|
+
})
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
type,
|
|
21
|
+
name,
|
|
22
|
+
instructions,
|
|
23
|
+
levels: question.levels.map((level) => typeof level === "string" ? { label: level } : level)
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
exports.toQuestionParam = toQuestionParam;
|
|
27
|
+
|
|
28
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs","names":[],"sources":["../../src/decisions/types.ts"],"sourcesContent":["import type { OpenAI as OpenAIClient } from \"openai\";\nimport type { BaseMessage, UsageMetadata } from \"@langchain/core/messages\";\n\ntype QuestionParam = OpenAIClient.DecisionCreateParams[\"questions\"][number];\n\n/** Estimate the probability that a condition is true. */\nexport interface Predicate {\n type: \"predicate\";\n instructions: string;\n}\n\n/** Select one option. Keys are the option values; values describe when each applies. */\nexport interface Choice<K extends string = string> {\n type: \"choice\";\n instructions: string;\n choices: Record<K, string | null>;\n}\n\n/** One level of a `Score` rubric. */\nexport type Level = OpenAIClient.DecisionCreateParams.QuestionParamScore.Level;\n\n/** Rate the input against two or more levels, ordered lowest to highest. */\nexport interface Score {\n type: \"score\";\n instructions: string;\n levels: readonly (string | Level)[];\n}\n\nexport type Question = Predicate | Choice | Score;\n\nexport type Questions = Record<string, Question>;\n\nexport type PredicateAnswer = Omit<\n OpenAIClient.Decision.AnswerResourcePredicate,\n \"name\"\n>;\n\nexport type ChoiceAnswer<K extends string = string> = Omit<\n OpenAIClient.Decision.AnswerResourceChoice,\n \"name\" | \"choice\" | \"probabilities\"\n> & {\n choice: K;\n probabilities: { value: K; probability: number }[];\n};\n\n/** `score` is the probability-weighted average of the zero-based level indices. */\nexport type ScoreAnswer = Omit<\n OpenAIClient.Decision.AnswerResourceScore,\n \"name\"\n>;\n\nexport type RefusalAnswer = Omit<\n OpenAIClient.Decision.AnswerResourceRefusal,\n \"name\"\n>;\n\nexport type Answer =\n | PredicateAnswer\n | ChoiceAnswer\n | ScoreAnswer\n | RefusalAnswer;\n\n/** The answer type a question produces. */\nexport type AnswerFor<T extends Question> = T extends Predicate\n ? PredicateAnswer\n : T extends Choice\n ? ChoiceAnswer<Extract<keyof T[\"choices\"], string>>\n : T extends Score\n ? ScoreAnswer\n : never;\n\n/** Answers keyed by question name, typed from the questions that were asked. */\nexport type Answers<Q extends Questions> = {\n -readonly [K in keyof Q]: AnswerFor<Q[K]> | RefusalAnswer;\n};\n\n/**\n * Text, LangChain messages, or JSON state to evaluate. Messages are sent as a native\n * conversation; JSON objects, which may contain messages, as an `input_json` part.\n */\nexport type DecisionInput =\n | string\n | BaseMessage\n | BaseMessage[]\n | Record<string, unknown>\n | Record<string, unknown>[];\n\n/** One Decisions request: what to evaluate and the named questions to ask. */\nexport interface DecisionRequest<Q extends Questions = Questions> {\n input: DecisionInput;\n questions: Q;\n}\n\nexport interface DecisionResult<Q extends Questions = Questions> {\n answers: Answers<Q>;\n /** The model that answered, as reported by the API. */\n model: string;\n requestId?: string;\n /** Read by LangSmith to record token usage on the traced run. */\n usage_metadata: UsageMetadata;\n}\n\n/** Converts a named question to the shape the Decisions API expects. */\nexport function toQuestionParam(\n name: string,\n question: Question\n): QuestionParam {\n const { type, instructions } = question;\n if (type === \"predicate\") return { type, name, instructions };\n if (type === \"choice\") {\n return {\n type,\n name,\n instructions,\n choices: Object.entries(question.choices).map(([value, description]) =>\n description == null ? { value } : { value, description }\n ),\n };\n }\n return {\n type,\n name,\n instructions,\n levels: question.levels.map((level) =>\n typeof level === \"string\" ? { label: level } : level\n ),\n };\n}\n"],"mappings":";;AAuGA,SAAgB,gBACd,MACA,UACe;CACf,MAAM,EAAE,MAAM,iBAAiB;CAC/B,IAAI,SAAS,aAAa,OAAO;EAAE;EAAM;EAAM;CAAa;CAC5D,IAAI,SAAS,UACX,OAAO;EACL;EACA;EACA;EACA,SAAS,OAAO,QAAQ,SAAS,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,iBACrD,eAAe,OAAO,EAAE,MAAM,IAAI;GAAE;GAAO;EAAY,CACzD;CACF;CAEF,OAAO;EACL;EACA;EACA;EACA,QAAQ,SAAS,OAAO,KAAK,UAC3B,OAAO,UAAU,WAAW,EAAE,OAAO,MAAM,IAAI,KACjD;CACF;AACF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { OpenAI } from "openai";
|
|
2
|
+
import { BaseMessage, UsageMetadata } from "@langchain/core/messages";
|
|
3
|
+
/** Estimate the probability that a condition is true. */
|
|
4
|
+
export interface Predicate {
|
|
5
|
+
type: "predicate";
|
|
6
|
+
instructions: string;
|
|
7
|
+
}
|
|
8
|
+
/** Select one option. Keys are the option values; values describe when each applies. */
|
|
9
|
+
export interface Choice<K extends string = string> {
|
|
10
|
+
type: "choice";
|
|
11
|
+
instructions: string;
|
|
12
|
+
choices: Record<K, string | null>;
|
|
13
|
+
}
|
|
14
|
+
/** One level of a `Score` rubric. */
|
|
15
|
+
export type Level = OpenAI.DecisionCreateParams.QuestionParamScore.Level;
|
|
16
|
+
/** Rate the input against two or more levels, ordered lowest to highest. */
|
|
17
|
+
export interface Score {
|
|
18
|
+
type: "score";
|
|
19
|
+
instructions: string;
|
|
20
|
+
levels: readonly (string | Level)[];
|
|
21
|
+
}
|
|
22
|
+
export type Question = Predicate | Choice | Score;
|
|
23
|
+
export type Questions = Record<string, Question>;
|
|
24
|
+
export type PredicateAnswer = Omit<OpenAI.Decision.AnswerResourcePredicate, "name">;
|
|
25
|
+
export type ChoiceAnswer<K extends string = string> = Omit<OpenAI.Decision.AnswerResourceChoice, "name" | "choice" | "probabilities"> & {
|
|
26
|
+
choice: K;
|
|
27
|
+
probabilities: {
|
|
28
|
+
value: K;
|
|
29
|
+
probability: number;
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
32
|
+
/** `score` is the probability-weighted average of the zero-based level indices. */
|
|
33
|
+
export type ScoreAnswer = Omit<OpenAI.Decision.AnswerResourceScore, "name">;
|
|
34
|
+
export type RefusalAnswer = Omit<OpenAI.Decision.AnswerResourceRefusal, "name">;
|
|
35
|
+
export type Answer = PredicateAnswer | ChoiceAnswer | ScoreAnswer | RefusalAnswer;
|
|
36
|
+
/** The answer type a question produces. */
|
|
37
|
+
export type AnswerFor<T extends Question> = T extends Predicate ? PredicateAnswer : T extends Choice ? ChoiceAnswer<Extract<keyof T["choices"], string>> : T extends Score ? ScoreAnswer : never;
|
|
38
|
+
/** Answers keyed by question name, typed from the questions that were asked. */
|
|
39
|
+
export type Answers<Q extends Questions> = { -readonly [K in keyof Q]: AnswerFor<Q[K]> | RefusalAnswer; };
|
|
40
|
+
/**
|
|
41
|
+
* Text, LangChain messages, or JSON state to evaluate. Messages are sent as a native
|
|
42
|
+
* conversation; JSON objects, which may contain messages, as an `input_json` part.
|
|
43
|
+
*/
|
|
44
|
+
export type DecisionInput = string | BaseMessage | BaseMessage[] | Record<string, unknown> | Record<string, unknown>[];
|
|
45
|
+
/** One Decisions request: what to evaluate and the named questions to ask. */
|
|
46
|
+
export interface DecisionRequest<Q extends Questions = Questions> {
|
|
47
|
+
input: DecisionInput;
|
|
48
|
+
questions: Q;
|
|
49
|
+
}
|
|
50
|
+
export interface DecisionResult<Q extends Questions = Questions> {
|
|
51
|
+
answers: Answers<Q>;
|
|
52
|
+
/** The model that answered, as reported by the API. */
|
|
53
|
+
model: string;
|
|
54
|
+
requestId?: string;
|
|
55
|
+
/** Read by LangSmith to record token usage on the traced run. */
|
|
56
|
+
usage_metadata: UsageMetadata;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":["OpenAIClient"],"sources":["../../src/decisions/types.ts"],"mappings":";;;iBAMiB;EACf;EACA;;;iBAIe,OAAO;EACtB;EACA;EACA,SAAS,OAAO;;;YAIN,QAAQA,OAAa,qBAAqB,mBAAmB;;iBAGxD;EACf;EACA;EACA,2BAA2B;;YAGjB,WAAW,YAAY,SAAS;YAEhC,YAAY,eAAe;YAE3B,kBAAkB,KAC5BA,OAAa,SAAS;YAIZ,aAAa,6BAA6B,KACpDA,OAAa,SAAS;EAGtB,QAAQ;EACR;IAAiB,OAAO;IAAG;;;;YAIjB,cAAc,KACxBA,OAAa,SAAS;YAIZ,gBAAgB,KAC1BA,OAAa,SAAS;YAIZ,SACR,kBACA,eACA,cACA;;YAGQ,UAAU,UAAU,YAAY,UAAU,YAClD,kBACA,UAAU,SACR,aAAa,cAAc,yBAC3B,UAAU,QACR;;YAII,QAAQ,UAAU,0BACjB,WAAW,IAAI,UAAU,EAAE,MAAM;;;;;YAOlC,yBAER,cACA,gBACA,0BACA;;iBAGa,gBAAgB,UAAU,YAAY;EACrD,OAAO;EACP,WAAW;;iBAGI,eAAe,UAAU,YAAY;EACpD,SAAS,QAAQ;;EAEjB;EACA;;EAEA,gBAAgB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { OpenAI } from "openai";
|
|
2
|
+
import { BaseMessage, UsageMetadata } from "@langchain/core/messages";
|
|
3
|
+
/** Estimate the probability that a condition is true. */
|
|
4
|
+
export interface Predicate {
|
|
5
|
+
type: "predicate";
|
|
6
|
+
instructions: string;
|
|
7
|
+
}
|
|
8
|
+
/** Select one option. Keys are the option values; values describe when each applies. */
|
|
9
|
+
export interface Choice<K extends string = string> {
|
|
10
|
+
type: "choice";
|
|
11
|
+
instructions: string;
|
|
12
|
+
choices: Record<K, string | null>;
|
|
13
|
+
}
|
|
14
|
+
/** One level of a `Score` rubric. */
|
|
15
|
+
export type Level = OpenAI.DecisionCreateParams.QuestionParamScore.Level;
|
|
16
|
+
/** Rate the input against two or more levels, ordered lowest to highest. */
|
|
17
|
+
export interface Score {
|
|
18
|
+
type: "score";
|
|
19
|
+
instructions: string;
|
|
20
|
+
levels: readonly (string | Level)[];
|
|
21
|
+
}
|
|
22
|
+
export type Question = Predicate | Choice | Score;
|
|
23
|
+
export type Questions = Record<string, Question>;
|
|
24
|
+
export type PredicateAnswer = Omit<OpenAI.Decision.AnswerResourcePredicate, "name">;
|
|
25
|
+
export type ChoiceAnswer<K extends string = string> = Omit<OpenAI.Decision.AnswerResourceChoice, "name" | "choice" | "probabilities"> & {
|
|
26
|
+
choice: K;
|
|
27
|
+
probabilities: {
|
|
28
|
+
value: K;
|
|
29
|
+
probability: number;
|
|
30
|
+
}[];
|
|
31
|
+
};
|
|
32
|
+
/** `score` is the probability-weighted average of the zero-based level indices. */
|
|
33
|
+
export type ScoreAnswer = Omit<OpenAI.Decision.AnswerResourceScore, "name">;
|
|
34
|
+
export type RefusalAnswer = Omit<OpenAI.Decision.AnswerResourceRefusal, "name">;
|
|
35
|
+
export type Answer = PredicateAnswer | ChoiceAnswer | ScoreAnswer | RefusalAnswer;
|
|
36
|
+
/** The answer type a question produces. */
|
|
37
|
+
export type AnswerFor<T extends Question> = T extends Predicate ? PredicateAnswer : T extends Choice ? ChoiceAnswer<Extract<keyof T["choices"], string>> : T extends Score ? ScoreAnswer : never;
|
|
38
|
+
/** Answers keyed by question name, typed from the questions that were asked. */
|
|
39
|
+
export type Answers<Q extends Questions> = { -readonly [K in keyof Q]: AnswerFor<Q[K]> | RefusalAnswer; };
|
|
40
|
+
/**
|
|
41
|
+
* Text, LangChain messages, or JSON state to evaluate. Messages are sent as a native
|
|
42
|
+
* conversation; JSON objects, which may contain messages, as an `input_json` part.
|
|
43
|
+
*/
|
|
44
|
+
export type DecisionInput = string | BaseMessage | BaseMessage[] | Record<string, unknown> | Record<string, unknown>[];
|
|
45
|
+
/** One Decisions request: what to evaluate and the named questions to ask. */
|
|
46
|
+
export interface DecisionRequest<Q extends Questions = Questions> {
|
|
47
|
+
input: DecisionInput;
|
|
48
|
+
questions: Q;
|
|
49
|
+
}
|
|
50
|
+
export interface DecisionResult<Q extends Questions = Questions> {
|
|
51
|
+
answers: Answers<Q>;
|
|
52
|
+
/** The model that answered, as reported by the API. */
|
|
53
|
+
model: string;
|
|
54
|
+
requestId?: string;
|
|
55
|
+
/** Read by LangSmith to record token usage on the traced run. */
|
|
56
|
+
usage_metadata: UsageMetadata;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":["OpenAIClient"],"sources":["../../src/decisions/types.ts"],"mappings":";;;iBAMiB;EACf;EACA;;;iBAIe,OAAO;EACtB;EACA;EACA,SAAS,OAAO;;;YAIN,QAAQA,OAAa,qBAAqB,mBAAmB;;iBAGxD;EACf;EACA;EACA,2BAA2B;;YAGjB,WAAW,YAAY,SAAS;YAEhC,YAAY,eAAe;YAE3B,kBAAkB,KAC5BA,OAAa,SAAS;YAIZ,aAAa,6BAA6B,KACpDA,OAAa,SAAS;EAGtB,QAAQ;EACR;IAAiB,OAAO;IAAG;;;;YAIjB,cAAc,KACxBA,OAAa,SAAS;YAIZ,gBAAgB,KAC1BA,OAAa,SAAS;YAIZ,SACR,kBACA,eACA,cACA;;YAGQ,UAAU,UAAU,YAAY,UAAU,YAClD,kBACA,UAAU,SACR,aAAa,cAAc,yBAC3B,UAAU,QACR;;YAII,QAAQ,UAAU,0BACjB,WAAW,IAAI,UAAU,EAAE,MAAM;;;;;YAOlC,yBAER,cACA,gBACA,0BACA;;iBAGa,gBAAgB,UAAU,YAAY;EACrD,OAAO;EACP,WAAW;;iBAGI,eAAe,UAAU,YAAY;EACpD,SAAS,QAAQ;;EAEjB;EACA;;EAEA,gBAAgB"}
|