@effect/ai-anthropic 0.0.2 → 0.0.4
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/dist/cjs/AnthropicClient.js +3 -2
- package/dist/cjs/AnthropicClient.js.map +1 -1
- package/dist/cjs/AnthropicCompletions.js +60 -7
- package/dist/cjs/AnthropicCompletions.js.map +1 -1
- package/dist/cjs/AnthropicConfig.js.map +1 -1
- package/dist/cjs/AnthropicTokenizer.js +6 -2
- package/dist/cjs/AnthropicTokenizer.js.map +1 -1
- package/dist/cjs/Generated.js +1 -1
- package/dist/cjs/Generated.js.map +1 -1
- package/dist/dts/AnthropicClient.d.ts +2 -1
- package/dist/dts/AnthropicClient.d.ts.map +1 -1
- package/dist/dts/AnthropicCompletions.d.ts +51 -1
- package/dist/dts/AnthropicCompletions.d.ts.map +1 -1
- package/dist/dts/AnthropicConfig.d.ts +1 -3
- package/dist/dts/AnthropicConfig.d.ts.map +1 -1
- package/dist/dts/AnthropicTokenizer.d.ts +5 -0
- package/dist/dts/AnthropicTokenizer.d.ts.map +1 -1
- package/dist/dts/Generated.d.ts +100 -1056
- package/dist/dts/Generated.d.ts.map +1 -1
- package/dist/esm/AnthropicClient.js +3 -2
- package/dist/esm/AnthropicClient.js.map +1 -1
- package/dist/esm/AnthropicCompletions.js +57 -6
- package/dist/esm/AnthropicCompletions.js.map +1 -1
- package/dist/esm/AnthropicConfig.js.map +1 -1
- package/dist/esm/AnthropicTokenizer.js +5 -1
- package/dist/esm/AnthropicTokenizer.js.map +1 -1
- package/dist/esm/Generated.js +1 -1
- package/dist/esm/Generated.js.map +1 -1
- package/package.json +5 -5
- package/src/AnthropicClient.ts +8 -2
- package/src/AnthropicCompletions.ts +197 -90
- package/src/AnthropicConfig.ts +1 -12
- package/src/AnthropicTokenizer.ts +5 -1
- package/src/Generated.ts +6 -7
|
@@ -3,22 +3,25 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { AiError } from "@effect/ai/AiError"
|
|
5
5
|
import type * as AiInput from "@effect/ai/AiInput"
|
|
6
|
+
import * as AiModel from "@effect/ai/AiModel"
|
|
6
7
|
import * as AiResponse from "@effect/ai/AiResponse"
|
|
7
8
|
import * as AiRole from "@effect/ai/AiRole"
|
|
8
9
|
import { addGenAIAnnotations } from "@effect/ai/AiTelemetry"
|
|
9
10
|
import * as Completions from "@effect/ai/Completions"
|
|
10
|
-
import
|
|
11
|
+
import * as Tokenizer from "@effect/ai/Tokenizer"
|
|
11
12
|
import * as Arr from "effect/Array"
|
|
12
13
|
import * as Chunk from "effect/Chunk"
|
|
14
|
+
import * as Context from "effect/Context"
|
|
13
15
|
import * as Effect from "effect/Effect"
|
|
16
|
+
import { dual } from "effect/Function"
|
|
14
17
|
import * as Layer from "effect/Layer"
|
|
15
18
|
import * as Option from "effect/Option"
|
|
16
19
|
import * as Predicate from "effect/Predicate"
|
|
17
20
|
import * as Stream from "effect/Stream"
|
|
18
21
|
import type { Span } from "effect/Tracer"
|
|
22
|
+
import type { Simplify } from "effect/Types"
|
|
19
23
|
import type { StreamChunk } from "./AnthropicClient.js"
|
|
20
24
|
import { AnthropicClient } from "./AnthropicClient.js"
|
|
21
|
-
import { AnthropicConfig } from "./AnthropicConfig.js"
|
|
22
25
|
import * as AnthropicTokenizer from "./AnthropicTokenizer.js"
|
|
23
26
|
import type * as Generated from "./Generated.js"
|
|
24
27
|
|
|
@@ -28,97 +31,166 @@ import type * as Generated from "./Generated.js"
|
|
|
28
31
|
*/
|
|
29
32
|
export type Model = typeof Generated.ModelEnum.Encoded
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const config = yield* AnthropicConfig.getOrUndefined
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// Configuration
|
|
36
|
+
// =============================================================================
|
|
35
37
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
38
|
+
/**
|
|
39
|
+
* @since 1.0.0
|
|
40
|
+
* @category tags
|
|
41
|
+
*/
|
|
42
|
+
export class Config extends Context.Tag("@effect/ai-anthropic/AnthropicCompletions/Config")<
|
|
43
|
+
Config,
|
|
44
|
+
Config.Service
|
|
45
|
+
>() {
|
|
46
|
+
/**
|
|
47
|
+
* @since 1.0.0
|
|
48
|
+
*/
|
|
49
|
+
static readonly getOrUndefined: Effect.Effect<typeof Config.Service | undefined> = Effect.map(
|
|
50
|
+
Effect.context<never>(),
|
|
51
|
+
(context) => context.unsafeMap.get(Config.key)
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @since 1.0.0
|
|
57
|
+
*/
|
|
58
|
+
export declare namespace Config {
|
|
59
|
+
/**
|
|
60
|
+
* @since 1.0.0
|
|
61
|
+
* @category configuration
|
|
62
|
+
*/
|
|
63
|
+
export interface Service extends
|
|
64
|
+
Simplify<
|
|
65
|
+
Partial<
|
|
66
|
+
Omit<
|
|
67
|
+
typeof Generated.CreateMessageParams.Encoded,
|
|
68
|
+
"messages" | "tools" | "tool_choice" | "stream"
|
|
69
|
+
>
|
|
70
|
+
>
|
|
71
|
+
>
|
|
72
|
+
{}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// =============================================================================
|
|
76
|
+
// Anthropic Completions
|
|
77
|
+
// =============================================================================
|
|
78
|
+
|
|
79
|
+
const modelCacheKey = Symbol.for("@effect/ai-anthropic/AnthropicCompletions/AiModel")
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @since 1.0.0
|
|
83
|
+
* @category ai models
|
|
84
|
+
*/
|
|
85
|
+
export const model = (
|
|
86
|
+
model: (string & {}) | Model,
|
|
87
|
+
config?: Omit<Config.Service, "model">
|
|
88
|
+
): AiModel.AiModel<Completions.Completions | Tokenizer.Tokenizer, AnthropicClient> =>
|
|
89
|
+
AiModel.make({
|
|
90
|
+
model,
|
|
91
|
+
cacheKey: modelCacheKey,
|
|
92
|
+
requires: AnthropicClient,
|
|
93
|
+
provides: make({ model, config }).pipe(
|
|
94
|
+
Effect.map((completions) =>
|
|
95
|
+
Context.merge(
|
|
96
|
+
Context.make(Completions.Completions, completions),
|
|
97
|
+
Context.make(Tokenizer.Tokenizer, AnthropicTokenizer.make)
|
|
98
|
+
)
|
|
68
99
|
)
|
|
100
|
+
),
|
|
101
|
+
updateContext: (context) => {
|
|
102
|
+
const innerConfig = context.unsafeMap.get(Config.key) as Config.Service | undefined
|
|
103
|
+
return Context.merge(context, Context.make(Config, { model, ...config, ...innerConfig }))
|
|
69
104
|
}
|
|
105
|
+
})
|
|
70
106
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
107
|
+
const make = Effect.fnUntraced(function*(options: {
|
|
108
|
+
readonly model: (string & {}) | Model
|
|
109
|
+
readonly config?: Omit<Config.Service, "model">
|
|
110
|
+
}) {
|
|
111
|
+
const client = yield* AnthropicClient
|
|
112
|
+
|
|
113
|
+
const makeRequest = ({ input, required, system, tools }: Completions.CompletionOptions) => {
|
|
114
|
+
const useStructured = tools.length === 1 && tools[0].structured
|
|
115
|
+
return Effect.map(
|
|
116
|
+
Effect.context<never>(),
|
|
117
|
+
(context): typeof Generated.CreateMessageParams.Encoded => ({
|
|
118
|
+
model: options.model,
|
|
119
|
+
// TODO: re-evaluate a better way to do this
|
|
120
|
+
max_tokens: 4096,
|
|
121
|
+
...options.config,
|
|
122
|
+
...context.unsafeMap.get(Config.key),
|
|
123
|
+
system: Option.getOrUndefined(system),
|
|
124
|
+
messages: makeMessages(input),
|
|
125
|
+
tools: tools.length === 0 ? undefined : tools.map((tool) => ({
|
|
126
|
+
name: tool.name,
|
|
127
|
+
description: tool.description,
|
|
128
|
+
input_schema: tool.parameters as any
|
|
129
|
+
})),
|
|
130
|
+
tool_choice: !useStructured && tools.length > 0
|
|
131
|
+
// For non-structured outputs, ensure tools are used if required
|
|
132
|
+
? typeof required === "boolean"
|
|
133
|
+
? required ? { type: "any" } : { type: "auto" }
|
|
134
|
+
: { type: "tool", name: required }
|
|
135
|
+
// For structured outputs, ensure the json output tool is used
|
|
136
|
+
: useStructured
|
|
137
|
+
? { type: "tool", name: tools[0].name }
|
|
138
|
+
: undefined
|
|
139
|
+
})
|
|
140
|
+
)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return yield* Completions.make({
|
|
144
|
+
create({ span, ...options }) {
|
|
145
|
+
return makeRequest(options).pipe(
|
|
146
|
+
Effect.tap((request) => annotateRequest(span, request)),
|
|
147
|
+
Effect.flatMap((payload) => client.client.messagesPost({ params: {}, payload })),
|
|
148
|
+
Effect.tap((response) => annotateChatResponse(span, response)),
|
|
149
|
+
Effect.flatMap((response) =>
|
|
150
|
+
makeResponse(
|
|
151
|
+
response,
|
|
152
|
+
"create",
|
|
153
|
+
options.tools.length === 1 && options.tools[0].structured
|
|
154
|
+
? options.tools[0]
|
|
155
|
+
: undefined
|
|
156
|
+
)
|
|
157
|
+
),
|
|
158
|
+
Effect.catchAll((cause) =>
|
|
159
|
+
Effect.fail(
|
|
160
|
+
new AiError({
|
|
161
|
+
module: "AnthropicCompletions",
|
|
162
|
+
method: "create",
|
|
163
|
+
description: "An error occurred",
|
|
164
|
+
cause
|
|
165
|
+
})
|
|
95
166
|
)
|
|
96
167
|
)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
)
|
|
168
|
+
)
|
|
169
|
+
},
|
|
170
|
+
stream({ span, ...options }) {
|
|
171
|
+
return makeRequest(options).pipe(
|
|
172
|
+
Effect.tap((request) => annotateRequest(span, request)),
|
|
173
|
+
Effect.map(client.stream),
|
|
174
|
+
Stream.unwrap,
|
|
175
|
+
Stream.tap((response) => {
|
|
176
|
+
annotateStreamResponse(span, response)
|
|
177
|
+
return Effect.void
|
|
178
|
+
}),
|
|
179
|
+
Stream.map((response) => response.asAiResponse),
|
|
180
|
+
Stream.catchAll((cause) =>
|
|
181
|
+
Effect.fail(
|
|
182
|
+
new AiError({
|
|
183
|
+
module: "AnthropicCompletions",
|
|
184
|
+
method: "stream",
|
|
185
|
+
description: "An error occurred",
|
|
186
|
+
cause
|
|
187
|
+
})
|
|
117
188
|
)
|
|
118
189
|
)
|
|
119
|
-
|
|
120
|
-
}
|
|
190
|
+
)
|
|
191
|
+
}
|
|
121
192
|
})
|
|
193
|
+
})
|
|
122
194
|
|
|
123
195
|
/**
|
|
124
196
|
* @since 1.0.0
|
|
@@ -126,7 +198,12 @@ const make = (options: { readonly model: (string & {}) | Model }) =>
|
|
|
126
198
|
*/
|
|
127
199
|
export const layerCompletions = (options: {
|
|
128
200
|
readonly model: (string & {}) | Model
|
|
129
|
-
|
|
201
|
+
readonly config?: Omit<Config.Service, "model">
|
|
202
|
+
}): Layer.Layer<Completions.Completions, never, AnthropicClient> =>
|
|
203
|
+
Layer.effect(
|
|
204
|
+
Completions.Completions,
|
|
205
|
+
make({ model: options.model, config: options.config })
|
|
206
|
+
)
|
|
130
207
|
|
|
131
208
|
/**
|
|
132
209
|
* @since 1.0.0
|
|
@@ -134,11 +211,41 @@ export const layerCompletions = (options: {
|
|
|
134
211
|
*/
|
|
135
212
|
export const layer = (options: {
|
|
136
213
|
readonly model: (string & {}) | Model
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
214
|
+
readonly config?: Omit<Config.Service, "model">
|
|
215
|
+
}): Layer.Layer<Completions.Completions | Tokenizer.Tokenizer, never, AnthropicClient> =>
|
|
216
|
+
Layer.merge(layerCompletions(options), AnthropicTokenizer.layer)
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* @since 1.0.0
|
|
220
|
+
* @category configuration
|
|
221
|
+
*/
|
|
222
|
+
export const withConfigOverride: {
|
|
223
|
+
/**
|
|
224
|
+
* @since 1.0.0
|
|
225
|
+
* @category configuration
|
|
226
|
+
*/
|
|
227
|
+
(config: Config.Service): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
|
|
228
|
+
/**
|
|
229
|
+
* @since 1.0.0
|
|
230
|
+
* @category configuration
|
|
231
|
+
*/
|
|
232
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, config: Config.Service): Effect.Effect<A, E, R>
|
|
233
|
+
} = dual<
|
|
234
|
+
/**
|
|
235
|
+
* @since 1.0.0
|
|
236
|
+
* @category configuration
|
|
237
|
+
*/
|
|
238
|
+
(config: Config.Service) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>,
|
|
239
|
+
/**
|
|
240
|
+
* @since 1.0.0
|
|
241
|
+
* @category configuration
|
|
242
|
+
*/
|
|
243
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, config: Config.Service) => Effect.Effect<A, E, R>
|
|
244
|
+
>(2, (self, overrides) =>
|
|
245
|
+
Effect.flatMap(
|
|
246
|
+
Config.getOrUndefined,
|
|
247
|
+
(config) => Effect.provideService(self, Config, { ...config, ...overrides })
|
|
248
|
+
))
|
|
142
249
|
|
|
143
250
|
const makeMessages = (
|
|
144
251
|
aiInput: AiInput.AiInput
|
package/src/AnthropicConfig.ts
CHANGED
|
@@ -5,8 +5,6 @@ import type { HttpClient } from "@effect/platform/HttpClient"
|
|
|
5
5
|
import * as Context from "effect/Context"
|
|
6
6
|
import * as Effect from "effect/Effect"
|
|
7
7
|
import { dual } from "effect/Function"
|
|
8
|
-
import type { Simplify } from "effect/Types"
|
|
9
|
-
import type * as Generated from "./Generated.js"
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* @since 1.0.0
|
|
@@ -34,16 +32,7 @@ export declare namespace AnthropicConfig {
|
|
|
34
32
|
* @since 1.0.0
|
|
35
33
|
* @category models
|
|
36
34
|
*/
|
|
37
|
-
export interface Service
|
|
38
|
-
Simplify<
|
|
39
|
-
Partial<
|
|
40
|
-
Omit<
|
|
41
|
-
typeof Generated.CreateMessageParams.Encoded,
|
|
42
|
-
"messages" | "tools" | "tool_choice" | "stream"
|
|
43
|
-
>
|
|
44
|
-
>
|
|
45
|
-
>
|
|
46
|
-
{
|
|
35
|
+
export interface Service {
|
|
47
36
|
readonly transformClient?: (client: HttpClient) => HttpClient
|
|
48
37
|
}
|
|
49
38
|
}
|
|
@@ -10,7 +10,11 @@ import * as Effect from "effect/Effect"
|
|
|
10
10
|
import * as Layer from "effect/Layer"
|
|
11
11
|
import * as Option from "effect/Option"
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
/**
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
* @category constructors
|
|
16
|
+
*/
|
|
17
|
+
export const make = Tokenizer.make({
|
|
14
18
|
tokenize(content) {
|
|
15
19
|
return Effect.try({
|
|
16
20
|
try: () => {
|
package/src/Generated.ts
CHANGED
|
@@ -14,17 +14,16 @@ export class MessagesPostParams extends S.Struct({
|
|
|
14
14
|
}) {}
|
|
15
15
|
|
|
16
16
|
export class ModelEnum extends S.Literal(
|
|
17
|
-
"claude-3-
|
|
18
|
-
"claude-3-
|
|
17
|
+
"claude-3-7-sonnet-latest",
|
|
18
|
+
"claude-3-7-sonnet-20250219",
|
|
19
19
|
"claude-3-5-sonnet-latest",
|
|
20
20
|
"claude-3-5-sonnet-20241022",
|
|
21
21
|
"claude-3-5-sonnet-20240620",
|
|
22
|
+
"claude-3-5-haiku-latest",
|
|
23
|
+
"claude-3-5-haiku-20241022",
|
|
24
|
+
"claude-3-5-haiku-20240307",
|
|
22
25
|
"claude-3-opus-latest",
|
|
23
|
-
"claude-3-opus-20240229"
|
|
24
|
-
"claude-3-sonnet-20240229",
|
|
25
|
-
"claude-3-haiku-20240307",
|
|
26
|
-
"claude-2.1",
|
|
27
|
-
"claude-2.0"
|
|
26
|
+
"claude-3-opus-20240229"
|
|
28
27
|
) {}
|
|
29
28
|
|
|
30
29
|
export class Model extends S.Union(S.String, ModelEnum) {}
|