@effect/ai 0.14.1 → 0.16.0
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/AiEmbeddingModel/package.json +6 -0
- package/AiLanguageModel/package.json +6 -0
- package/AiTool/package.json +6 -0
- package/dist/cjs/AiChat.js +65 -86
- package/dist/cjs/AiChat.js.map +1 -1
- package/dist/cjs/{Embeddings.js → AiEmbeddingModel.js} +12 -12
- package/dist/cjs/AiEmbeddingModel.js.map +1 -0
- package/dist/cjs/AiError.js +8 -1
- package/dist/cjs/AiError.js.map +1 -1
- package/dist/cjs/AiInput.js +335 -248
- package/dist/cjs/AiInput.js.map +1 -1
- package/dist/cjs/AiLanguageModel.js +311 -0
- package/dist/cjs/AiLanguageModel.js.map +1 -0
- package/dist/cjs/AiModel.js +11 -5
- package/dist/cjs/AiModel.js.map +1 -1
- package/dist/cjs/AiPlan.js +10 -3
- package/dist/cjs/AiPlan.js.map +1 -1
- package/dist/cjs/AiResponse.js +481 -165
- package/dist/cjs/AiResponse.js.map +1 -1
- package/dist/cjs/AiTelemetry.js +10 -3
- package/dist/cjs/AiTelemetry.js.map +1 -1
- package/dist/cjs/AiTool.js +93 -0
- package/dist/cjs/AiTool.js.map +1 -0
- package/dist/cjs/AiToolkit.js +121 -98
- package/dist/cjs/AiToolkit.js.map +1 -1
- package/dist/cjs/Tokenizer.js +14 -16
- package/dist/cjs/Tokenizer.js.map +1 -1
- package/dist/cjs/index.js +7 -9
- package/dist/cjs/internal/aiPlan.js +6 -9
- package/dist/cjs/internal/aiPlan.js.map +1 -1
- package/dist/cjs/internal/common.js +22 -0
- package/dist/cjs/internal/common.js.map +1 -0
- package/dist/dts/AiChat.d.ts +58 -44
- package/dist/dts/AiChat.d.ts.map +1 -1
- package/dist/dts/{Embeddings.d.ts → AiEmbeddingModel.d.ts} +13 -14
- package/dist/dts/AiEmbeddingModel.d.ts.map +1 -0
- package/dist/dts/AiError.d.ts +4 -3
- package/dist/dts/AiError.d.ts.map +1 -1
- package/dist/dts/AiInput.d.ts +441 -146
- package/dist/dts/AiInput.d.ts.map +1 -1
- package/dist/dts/AiLanguageModel.d.ts +263 -0
- package/dist/dts/AiLanguageModel.d.ts.map +1 -0
- package/dist/dts/AiModel.d.ts +21 -20
- package/dist/dts/AiModel.d.ts.map +1 -1
- package/dist/dts/AiPlan.d.ts +90 -26
- package/dist/dts/AiPlan.d.ts.map +1 -1
- package/dist/dts/AiResponse.d.ts +711 -100
- package/dist/dts/AiResponse.d.ts.map +1 -1
- package/dist/dts/AiTelemetry.d.ts +175 -157
- package/dist/dts/AiTelemetry.d.ts.map +1 -1
- package/dist/dts/AiTool.d.ts +288 -0
- package/dist/dts/AiTool.d.ts.map +1 -0
- package/dist/dts/AiToolkit.d.ts +50 -111
- package/dist/dts/AiToolkit.d.ts.map +1 -1
- package/dist/dts/Tokenizer.d.ts +8 -6
- package/dist/dts/Tokenizer.d.ts.map +1 -1
- package/dist/dts/index.d.ts +8 -12
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/common.d.ts +2 -0
- package/dist/dts/internal/common.d.ts.map +1 -0
- package/dist/esm/AiChat.js +62 -83
- package/dist/esm/AiChat.js.map +1 -1
- package/dist/esm/{Embeddings.js → AiEmbeddingModel.js} +10 -10
- package/dist/esm/AiEmbeddingModel.js.map +1 -0
- package/dist/esm/AiError.js +8 -1
- package/dist/esm/AiError.js.map +1 -1
- package/dist/esm/AiInput.js +316 -238
- package/dist/esm/AiInput.js.map +1 -1
- package/dist/esm/AiLanguageModel.js +300 -0
- package/dist/esm/AiLanguageModel.js.map +1 -0
- package/dist/esm/AiModel.js +11 -5
- package/dist/esm/AiModel.js.map +1 -1
- package/dist/esm/AiPlan.js +8 -2
- package/dist/esm/AiPlan.js.map +1 -1
- package/dist/esm/AiResponse.js +467 -162
- package/dist/esm/AiResponse.js.map +1 -1
- package/dist/esm/AiTelemetry.js +8 -2
- package/dist/esm/AiTelemetry.js.map +1 -1
- package/dist/esm/AiTool.js +82 -0
- package/dist/esm/AiTool.js.map +1 -0
- package/dist/esm/AiToolkit.js +118 -96
- package/dist/esm/AiToolkit.js.map +1 -1
- package/dist/esm/Tokenizer.js +14 -16
- package/dist/esm/Tokenizer.js.map +1 -1
- package/dist/esm/index.js +8 -12
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/aiPlan.js +4 -7
- package/dist/esm/internal/aiPlan.js.map +1 -1
- package/dist/esm/internal/common.js +14 -0
- package/dist/esm/internal/common.js.map +1 -0
- package/package.json +28 -36
- package/src/AiChat.ts +182 -207
- package/src/{Embeddings.ts → AiEmbeddingModel.ts} +19 -18
- package/src/AiError.ts +8 -1
- package/src/AiInput.ts +434 -313
- package/src/AiLanguageModel.ts +569 -0
- package/src/AiModel.ts +47 -29
- package/src/AiPlan.ts +102 -30
- package/src/AiResponse.ts +743 -187
- package/src/AiTelemetry.ts +214 -197
- package/src/AiTool.ts +496 -0
- package/src/AiToolkit.ts +200 -240
- package/src/Tokenizer.ts +18 -22
- package/src/index.ts +9 -14
- package/src/internal/aiPlan.ts +12 -14
- package/src/internal/common.ts +12 -0
- package/AiModels/package.json +0 -6
- package/AiRole/package.json +0 -6
- package/Completions/package.json +0 -6
- package/Embeddings/package.json +0 -6
- package/dist/cjs/AiModels.js +0 -54
- package/dist/cjs/AiModels.js.map +0 -1
- package/dist/cjs/AiRole.js +0 -106
- package/dist/cjs/AiRole.js.map +0 -1
- package/dist/cjs/Completions.js +0 -256
- package/dist/cjs/Completions.js.map +0 -1
- package/dist/cjs/Embeddings.js.map +0 -1
- package/dist/dts/AiModels.d.ts +0 -34
- package/dist/dts/AiModels.d.ts.map +0 -1
- package/dist/dts/AiRole.d.ts +0 -111
- package/dist/dts/AiRole.d.ts.map +0 -1
- package/dist/dts/Completions.d.ts +0 -128
- package/dist/dts/Completions.d.ts.map +0 -1
- package/dist/dts/Embeddings.d.ts.map +0 -1
- package/dist/esm/AiModels.js +0 -44
- package/dist/esm/AiModels.js.map +0 -1
- package/dist/esm/AiRole.js +0 -93
- package/dist/esm/AiRole.js.map +0 -1
- package/dist/esm/Completions.js +0 -245
- package/dist/esm/Completions.js.map +0 -1
- package/dist/esm/Embeddings.js.map +0 -1
- package/src/AiModels.ts +0 -77
- package/src/AiRole.ts +0 -122
- package/src/Completions.ts +0 -434
package/src/AiToolkit.ts
CHANGED
|
@@ -3,299 +3,259 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import * as Context from "effect/Context"
|
|
5
5
|
import * as Effect from "effect/Effect"
|
|
6
|
-
import
|
|
7
|
-
import {
|
|
8
|
-
import
|
|
9
|
-
import * as Inspectable from "effect/Inspectable"
|
|
6
|
+
import { CommitPrototype } from "effect/Effectable"
|
|
7
|
+
import type { Inspectable } from "effect/Inspectable"
|
|
8
|
+
import { BaseProto as InspectableProto } from "effect/Inspectable"
|
|
10
9
|
import * as Layer from "effect/Layer"
|
|
10
|
+
import type { ParseError } from "effect/ParseResult"
|
|
11
|
+
import type { Pipeable } from "effect/Pipeable"
|
|
11
12
|
import { pipeArguments } from "effect/Pipeable"
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import type * as
|
|
13
|
+
import * as Predicate from "effect/Predicate"
|
|
14
|
+
import * as Schema from "effect/Schema"
|
|
15
|
+
import type * as Scope from "effect/Scope"
|
|
16
|
+
import { AiError } from "./AiError.js"
|
|
17
|
+
import * as AiTool from "./AiTool.js"
|
|
15
18
|
|
|
16
19
|
/**
|
|
17
20
|
* @since 1.0.0
|
|
18
|
-
* @category
|
|
21
|
+
* @category Type Ids
|
|
19
22
|
*/
|
|
20
23
|
export const TypeId: unique symbol = Symbol.for("@effect/ai/AiToolkit")
|
|
21
24
|
|
|
22
25
|
/**
|
|
23
26
|
* @since 1.0.0
|
|
24
|
-
* @category
|
|
27
|
+
* @category Type Ids
|
|
25
28
|
*/
|
|
26
29
|
export type TypeId = typeof TypeId
|
|
27
30
|
|
|
28
31
|
/**
|
|
32
|
+
* An `AiToolkit` represents a set of tools that a large language model can
|
|
33
|
+
* use to augment its response.
|
|
34
|
+
*
|
|
29
35
|
* @since 1.0.0
|
|
30
|
-
* @category
|
|
36
|
+
* @category Models
|
|
31
37
|
*/
|
|
32
|
-
export interface AiToolkit<in out Tools extends
|
|
33
|
-
extends Effect.Effect<
|
|
38
|
+
export interface AiToolkit<in out Tools extends AiTool.Any>
|
|
39
|
+
extends Effect.Effect<ToHandler<Tools>, never, AiTool.ToHandler<Tools>>, Inspectable, Pipeable
|
|
34
40
|
{
|
|
35
|
-
|
|
36
|
-
readonly tools: HashMap.HashMap<string, Tools>
|
|
37
|
-
readonly add: <S extends Tool.AnySchema>(tool: S) => AiToolkit<Tools | S>
|
|
38
|
-
readonly addAll: <ToAdd extends ReadonlyArray<Tool.AnySchema>>(
|
|
39
|
-
...tools: ToAdd
|
|
40
|
-
) => AiToolkit<Tools | ToAdd[number]>
|
|
41
|
-
readonly concat: <T extends Tool.AnySchema>(that: AiToolkit<T>) => AiToolkit<Tools | T>
|
|
42
|
-
readonly implement: <R, EX = never, RX = never>(
|
|
43
|
-
f: (
|
|
44
|
-
handlers: Handlers<Tools>
|
|
45
|
-
) => Handlers<never, R> | Effect.Effect<Handlers<never, R>, EX, RX>
|
|
46
|
-
) => Layer.Layer<Tool.ServiceFromTag<Tools["_tag"]> | Registry, EX, Exclude<R | RX, Scope>>
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* @since 1.0.0
|
|
51
|
-
* @category models
|
|
52
|
-
*/
|
|
53
|
-
export declare namespace AiToolkit {
|
|
54
|
-
/**
|
|
55
|
-
* @since 1.0.0
|
|
56
|
-
* @category models
|
|
57
|
-
*/
|
|
58
|
-
export type Tools<A> = A extends AiToolkit<infer Tools> ? Tools : never
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* @since 1.0.0
|
|
62
|
-
* @category models
|
|
63
|
-
*/
|
|
64
|
-
export type SuccessSchema<A> = A extends AiToolkit<infer Tools> ? Tools["success"] : never
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* @since 1.0.0
|
|
69
|
-
* @category tool
|
|
70
|
-
*/
|
|
71
|
-
export declare namespace Tool {
|
|
72
|
-
/**
|
|
73
|
-
* @since 1.0.0
|
|
74
|
-
* @category tool
|
|
75
|
-
*/
|
|
76
|
-
export interface AnySchema {
|
|
77
|
-
readonly [Schema.TypeId]: any
|
|
78
|
-
readonly _tag: string
|
|
79
|
-
readonly Type: Schema.SerializableWithResult.All
|
|
80
|
-
readonly success: Schema.Schema.Any
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* @since 1.0.0
|
|
85
|
-
* @category tool
|
|
86
|
-
*/
|
|
87
|
-
export type Success<Tool extends AnySchema> = Schema.WithResult.Success<Tool["Type"]>
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* @since 1.0.0
|
|
91
|
-
* @category tool
|
|
92
|
-
*/
|
|
93
|
-
export type Failure<Tool extends AnySchema> = Schema.WithResult.Failure<Tool["Type"]>
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* @since 1.0.0
|
|
97
|
-
* @category tool
|
|
98
|
-
*/
|
|
99
|
-
export type Context<Tool extends AnySchema> = Schema.WithResult.Context<Tool["Type"]>
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* @since 1.0.0
|
|
103
|
-
* @category tool
|
|
104
|
-
*/
|
|
105
|
-
export type Handler<Tool extends AnySchema, R> = (
|
|
106
|
-
params: Tool["Type"]
|
|
107
|
-
) => Effect.Effect<Success<Tool>, Failure<Tool>, R>
|
|
41
|
+
new(_: never): {}
|
|
108
42
|
|
|
109
|
-
|
|
110
|
-
* @since 1.0.0
|
|
111
|
-
* @category tool
|
|
112
|
-
*/
|
|
113
|
-
export type HandlerAny = (params: any) => Effect.Effect<any, any, any>
|
|
43
|
+
readonly [TypeId]: TypeId
|
|
114
44
|
|
|
115
45
|
/**
|
|
116
|
-
*
|
|
117
|
-
* @category tool
|
|
46
|
+
* A map containing the tools that are part of this toolkit.
|
|
118
47
|
*/
|
|
119
|
-
|
|
120
|
-
readonly _: unique symbol
|
|
121
|
-
readonly name: Types.Invariant<Tag>
|
|
122
|
-
}
|
|
48
|
+
readonly tools: AiTool.ByName<Tools>
|
|
123
49
|
|
|
124
50
|
/**
|
|
125
|
-
*
|
|
126
|
-
*
|
|
51
|
+
* Converts this toolkit into a `Context` object containing the handlers for
|
|
52
|
+
* all tools in the toolkit.
|
|
127
53
|
*/
|
|
128
|
-
|
|
54
|
+
toContext<Handlers extends HandlersFrom<Tools>, EX = never, RX = never>(
|
|
55
|
+
build: Handlers | Effect.Effect<Handlers, EX, RX>
|
|
56
|
+
): Effect.Effect<Context.Context<AiTool.ToHandler<Tools>>, EX, RX>
|
|
129
57
|
|
|
130
58
|
/**
|
|
131
|
-
*
|
|
132
|
-
*
|
|
59
|
+
* Converts this toolkit into a `Layer` containing the handlers for all tools
|
|
60
|
+
* in the toolkit.
|
|
133
61
|
*/
|
|
134
|
-
|
|
62
|
+
toLayer<Handlers extends HandlersFrom<Tools>, EX = never, RX = never>(
|
|
63
|
+
build: Handlers | Effect.Effect<Handlers, EX, RX>
|
|
64
|
+
): Layer.Layer<AiTool.ToHandler<Tools>, EX, Exclude<RX, Scope.Scope>>
|
|
135
65
|
}
|
|
136
66
|
|
|
137
67
|
/**
|
|
138
68
|
* @since 1.0.0
|
|
139
|
-
* @category
|
|
69
|
+
* @category Models
|
|
140
70
|
*/
|
|
141
|
-
export
|
|
142
|
-
Registry,
|
|
143
|
-
Map<Tool.AnySchema, Tool.HandlerAny>
|
|
144
|
-
>() {
|
|
145
|
-
static readonly Live: Layer.Layer<Registry> = Layer.sync(Registry, () => new Map())
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
class AiToolkitImpl<Tools extends Tool.AnySchema>
|
|
149
|
-
extends Effectable.Class<Handlers<Tools>, never, Tool.Services<Tools> | Registry>
|
|
150
|
-
implements AiToolkit<Tools>
|
|
151
|
-
{
|
|
71
|
+
export interface Any {
|
|
152
72
|
readonly [TypeId]: TypeId
|
|
153
|
-
|
|
154
|
-
super()
|
|
155
|
-
this[TypeId] = TypeId
|
|
156
|
-
}
|
|
157
|
-
toJSON(): unknown {
|
|
158
|
-
return {
|
|
159
|
-
_id: "@effect/ai/AiToolkit",
|
|
160
|
-
tools: [...HashMap.values(this.tools)].map((tool) => tool._tag)
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
toString(): string {
|
|
164
|
-
return Inspectable.format(this)
|
|
165
|
-
}
|
|
166
|
-
[Inspectable.NodeInspectSymbol](): string {
|
|
167
|
-
return Inspectable.format(this)
|
|
168
|
-
}
|
|
169
|
-
pipe() {
|
|
170
|
-
return pipeArguments(this, arguments)
|
|
171
|
-
}
|
|
172
|
-
add<S extends Tool.AnySchema>(tool: S): AiToolkit<Tools | S> {
|
|
173
|
-
return new AiToolkitImpl(HashMap.set(this.tools, tool._tag, tool as any)) as any
|
|
174
|
-
}
|
|
175
|
-
addAll<ToAdd extends ReadonlyArray<Tool.AnySchema>>(...tools: ToAdd): AiToolkit<Tools | ToAdd[number]> {
|
|
176
|
-
let map = this.tools
|
|
177
|
-
for (const tool of tools) {
|
|
178
|
-
map = HashMap.set(map, tool._tag, tool as any)
|
|
179
|
-
}
|
|
180
|
-
return new AiToolkitImpl(map as any)
|
|
181
|
-
}
|
|
182
|
-
concat<T extends Tool.AnySchema>(that: AiToolkit<T>): AiToolkit<Tools | T> {
|
|
183
|
-
return new AiToolkitImpl(HashMap.union(this.tools, that.tools))
|
|
184
|
-
}
|
|
185
|
-
implement<R, EX = never, RX = never>(
|
|
186
|
-
f: (
|
|
187
|
-
handlers: Handlers<Tools>
|
|
188
|
-
) => Handlers<never, R> | Effect.Effect<Handlers<never, R>, EX, RX>
|
|
189
|
-
): Layer.Layer<Tool.ServiceFromTag<Tools["_tag"]> | Registry, EX, Exclude<R | RX, Scope>> {
|
|
190
|
-
return registerHandlers(this as any, f as any).pipe(Layer.scopedDiscard, Layer.provideMerge(Registry.Live))
|
|
191
|
-
}
|
|
192
|
-
commit(): Effect.Effect<Handlers<Tools>, never, Tool.ServiceFromTag<Tools["_tag"]> | Registry> {
|
|
193
|
-
return Effect.map(Registry, (map) => {
|
|
194
|
-
let handlers = HashMap.empty<string, Tool.HandlerAny>()
|
|
195
|
-
for (const [tag, tool] of this.tools) {
|
|
196
|
-
handlers = HashMap.set(handlers, tag, map.get(tool)!)
|
|
197
|
-
}
|
|
198
|
-
return new HandlersImpl(this as any, handlers)
|
|
199
|
-
}) as any
|
|
200
|
-
}
|
|
73
|
+
readonly tools: ReadonlyMap<string, AiTool.Any>
|
|
201
74
|
}
|
|
202
75
|
|
|
203
|
-
const registerHandlers = (
|
|
204
|
-
toolkit: AiToolkit<any>,
|
|
205
|
-
f: (handlers: Handlers<any, any>) => Handlers<any, any> | Effect.Effect<Handlers<any, any>>
|
|
206
|
-
) =>
|
|
207
|
-
Effect.context<any>().pipe(
|
|
208
|
-
Effect.bindTo("context"),
|
|
209
|
-
Effect.bind("handlers", () => {
|
|
210
|
-
const handlers = f(HandlersImpl.fromToolkit(toolkit))
|
|
211
|
-
return Effect.isEffect(handlers) ? handlers : Effect.succeed(handlers)
|
|
212
|
-
}),
|
|
213
|
-
Effect.tap(({ context, handlers }) => {
|
|
214
|
-
const registry = Context.unsafeGet(context, Registry)
|
|
215
|
-
for (const [tag, handler] of handlers.handlers) {
|
|
216
|
-
const tool = HashMap.unsafeGet(handlers.toolkit.tools, tag)
|
|
217
|
-
registry.set(tool, function(params: any) {
|
|
218
|
-
return Effect.withSpan(
|
|
219
|
-
Effect.mapInputContext(handler(params), (input) => Context.merge(input, context)),
|
|
220
|
-
"AiToolkit.handler",
|
|
221
|
-
{
|
|
222
|
-
captureStackTrace: false,
|
|
223
|
-
attributes: {
|
|
224
|
-
tool: tag,
|
|
225
|
-
parameters: params
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
)
|
|
229
|
-
})
|
|
230
|
-
}
|
|
231
|
-
})
|
|
232
|
-
)
|
|
233
|
-
|
|
234
76
|
/**
|
|
77
|
+
* Represents an `AiToolkit` which has been augmented with a handler function
|
|
78
|
+
* for resolving tool call requests.
|
|
79
|
+
*
|
|
235
80
|
* @since 1.0.0
|
|
236
|
-
* @category
|
|
81
|
+
* @category Models
|
|
237
82
|
*/
|
|
238
|
-
export
|
|
83
|
+
export interface ToHandler<in out Tool extends AiTool.Any> {
|
|
84
|
+
readonly tools: ReadonlyArray<Tool>
|
|
85
|
+
readonly handle: (toolName: AiTool.Name<Tool>, toolParams: AiTool.Parameters<Tool>) => AiTool.HandlerEffect<Tool>
|
|
86
|
+
}
|
|
239
87
|
|
|
240
88
|
/**
|
|
89
|
+
* A utility mapped type which associates tool names with their handlers.
|
|
90
|
+
*
|
|
241
91
|
* @since 1.0.0
|
|
242
|
-
* @category
|
|
92
|
+
* @category Utility Types
|
|
243
93
|
*/
|
|
244
|
-
export
|
|
94
|
+
export type HandlersFrom<Tool extends AiTool.Any> = {
|
|
95
|
+
[Name in Tool as Tool["name"]]: (params: AiTool.Parameters<Tool>) => AiTool.HandlerEffect<Tool>
|
|
96
|
+
}
|
|
245
97
|
|
|
246
98
|
/**
|
|
99
|
+
* A utility type which returns the tools in an `AiToolkit`.
|
|
100
|
+
*
|
|
247
101
|
* @since 1.0.0
|
|
248
|
-
* @category
|
|
102
|
+
* @category Utility Types
|
|
249
103
|
*/
|
|
250
|
-
export type
|
|
104
|
+
export type Tools<Toolkit> = Toolkit extends AiToolkit<infer Tool> ? string extends Tool["name"] ? never : Tool : never
|
|
105
|
+
|
|
106
|
+
const Proto = {
|
|
107
|
+
...CommitPrototype,
|
|
108
|
+
...InspectableProto,
|
|
109
|
+
[TypeId]: TypeId,
|
|
110
|
+
toContext(this: AiToolkit<any>, build: Effect.Effect<Record<string, (params: any) => any>>) {
|
|
111
|
+
return Effect.gen(this, function*() {
|
|
112
|
+
const context = yield* Effect.context<never>()
|
|
113
|
+
const handlers = Effect.isEffect(build) ? yield* build : build
|
|
114
|
+
const contextMap = new Map<string, unknown>()
|
|
115
|
+
for (const [name, handler] of Object.entries(handlers)) {
|
|
116
|
+
const tool = this.tools[name]!
|
|
117
|
+
contextMap.set(tool.key, { handler, context })
|
|
118
|
+
}
|
|
119
|
+
return Context.unsafeMake(contextMap)
|
|
120
|
+
})
|
|
121
|
+
},
|
|
122
|
+
toLayer(this: AiToolkit<any>, build: Effect.Effect<Record<string, (params: any) => any>>) {
|
|
123
|
+
return Layer.scopedContext(this.toContext(build))
|
|
124
|
+
},
|
|
125
|
+
commit(this: AiToolkit<AiTool.AnyWithProtocol>) {
|
|
126
|
+
return Effect.gen(this, function*() {
|
|
127
|
+
const context = yield* Effect.context<never>()
|
|
128
|
+
const tools = this.tools
|
|
129
|
+
const schemasCache = new WeakMap<any, {
|
|
130
|
+
readonly context: Context.Context<never>
|
|
131
|
+
readonly handler: (params: any) => Effect.Effect<any, any>
|
|
132
|
+
readonly encodeSuccess: (u: unknown) => Effect.Effect<unknown, ParseError>
|
|
133
|
+
readonly decodeFailure: (u: unknown) => Effect.Effect<AiTool.Failure<any>, ParseError>
|
|
134
|
+
readonly decodeParameters: (u: unknown) => Effect.Effect<AiTool.Parameters<any>, ParseError>
|
|
135
|
+
}>()
|
|
136
|
+
const getSchemas = (tool: AiTool.AnyWithProtocol) => {
|
|
137
|
+
let schemas = schemasCache.get(tool)
|
|
138
|
+
if (Predicate.isUndefined(schemas)) {
|
|
139
|
+
const handler = context.unsafeMap.get(tool.key)! as AiTool.Handler<any>
|
|
140
|
+
const encodeSuccess = Schema.encodeUnknown(tool.successSchema) as any
|
|
141
|
+
const decodeFailure = Schema.decodeUnknown(tool.failureSchema as any) as any
|
|
142
|
+
const decodeParameters = Schema.decodeUnknown(tool.parametersSchema) as any
|
|
143
|
+
schemas = {
|
|
144
|
+
context: handler.context,
|
|
145
|
+
handler: handler.handler,
|
|
146
|
+
encodeSuccess,
|
|
147
|
+
decodeFailure,
|
|
148
|
+
decodeParameters
|
|
149
|
+
}
|
|
150
|
+
schemasCache.set(tool, schemas)
|
|
151
|
+
}
|
|
152
|
+
return schemas
|
|
153
|
+
}
|
|
154
|
+
const handle = Effect.fn("AiToolkit.handler", { captureStackTrace: false })(
|
|
155
|
+
function*(toolName: string, toolParams: unknown) {
|
|
156
|
+
yield* Effect.annotateCurrentSpan({
|
|
157
|
+
tool: toolName,
|
|
158
|
+
parameters: toolParams
|
|
159
|
+
})
|
|
160
|
+
const tool = tools[toolName]!
|
|
161
|
+
const schemas = getSchemas(tool)
|
|
162
|
+
const decodedParams = yield* Effect.mapError(
|
|
163
|
+
schemas.decodeParameters(toolParams),
|
|
164
|
+
(cause) =>
|
|
165
|
+
new AiError({
|
|
166
|
+
module: "AiToolkit",
|
|
167
|
+
method: `${toolName}.handle`,
|
|
168
|
+
description: `Failed to decode tool call parameters for tool '${toolName}' from '${toolParams}'`,
|
|
169
|
+
cause
|
|
170
|
+
})
|
|
171
|
+
)
|
|
172
|
+
const result = yield* schemas.handler(decodedParams).pipe(
|
|
173
|
+
Effect.mapInputContext((input) => Context.merge(schemas.context, input)),
|
|
174
|
+
Effect.catchAll((error) =>
|
|
175
|
+
schemas.decodeFailure(error).pipe(
|
|
176
|
+
Effect.mapError((cause) =>
|
|
177
|
+
new AiError({
|
|
178
|
+
module: "AiToolkit",
|
|
179
|
+
method: `${toolName}.handle`,
|
|
180
|
+
description: `Failed to decode tool call failure for tool '${toolName}'`,
|
|
181
|
+
cause
|
|
182
|
+
})
|
|
183
|
+
),
|
|
184
|
+
Effect.flatMap(Effect.fail)
|
|
185
|
+
)
|
|
186
|
+
)
|
|
187
|
+
)
|
|
188
|
+
const encodedResult = yield* Effect.mapError(
|
|
189
|
+
schemas.encodeSuccess(result),
|
|
190
|
+
(cause) =>
|
|
191
|
+
new AiError({
|
|
192
|
+
module: "AiToolkit",
|
|
193
|
+
method: `${toolName}.handle`,
|
|
194
|
+
description: `Failed to encode tool call result for tool '${toolName}'`,
|
|
195
|
+
cause
|
|
196
|
+
})
|
|
197
|
+
)
|
|
198
|
+
return {
|
|
199
|
+
result,
|
|
200
|
+
encodedResult
|
|
201
|
+
} satisfies AiTool.HandlerResult<any>
|
|
202
|
+
}
|
|
203
|
+
)
|
|
204
|
+
return {
|
|
205
|
+
tools: Array.from(Object.values(tools)),
|
|
206
|
+
handle
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
},
|
|
210
|
+
toJSON(this: AiToolkit<any>): unknown {
|
|
211
|
+
return {
|
|
212
|
+
_id: "@effect/ai/AiToolkit",
|
|
213
|
+
tools: Array.from(Object.values(this.tools)).map((tool) => tool.name)
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
pipe() {
|
|
217
|
+
return pipeArguments(this, arguments)
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const makeProto = <Tools extends AiTool.Any>(tools: Record<string, Tools>): AiToolkit<Tools> =>
|
|
222
|
+
Object.assign(function() {}, Proto, { tools }) as any
|
|
223
|
+
|
|
224
|
+
const resolveInput = <Tools extends ReadonlyArray<AiTool.Any>>(
|
|
225
|
+
...tools: Tools
|
|
226
|
+
): Record<string, Tools[number]> => {
|
|
227
|
+
const output = {} as Record<string, Tools[number]>
|
|
228
|
+
for (const tool of tools) {
|
|
229
|
+
const value = (Schema.isSchema(tool) ? AiTool.fromTaggedRequest(tool as any) : tool) as any
|
|
230
|
+
output[tool.name] = value
|
|
231
|
+
}
|
|
232
|
+
return output
|
|
233
|
+
}
|
|
251
234
|
|
|
252
235
|
/**
|
|
236
|
+
* Constructs a new `AiToolkit` from the specified tools.
|
|
237
|
+
*
|
|
253
238
|
* @since 1.0.0
|
|
254
|
-
* @category
|
|
239
|
+
* @category Constructors
|
|
255
240
|
*/
|
|
256
|
-
export
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
readonly handlers: HashMap.HashMap<string, Tool.Handler<any, R>>
|
|
260
|
-
readonly handle: <Tag extends Types.Tags<Tools>, RH>(
|
|
261
|
-
tag: Tag,
|
|
262
|
-
f: Tool.Handler<Types.ExtractTag<Tools, Tag>, RH>
|
|
263
|
-
) => Handlers<Types.ExcludeTag<Tools, Tag>, R | RH | Tool.Context<Types.ExtractTag<Tools, Tag>>>
|
|
264
|
-
}
|
|
241
|
+
export const make = <const Tools extends ReadonlyArray<AiTool.Any>>(
|
|
242
|
+
...tools: Tools
|
|
243
|
+
): AiToolkit<Tools[number]> => makeProto(resolveInput(...tools))
|
|
265
244
|
|
|
266
245
|
/**
|
|
246
|
+
* Merges this toolkit with one or more other toolkits.
|
|
247
|
+
*
|
|
267
248
|
* @since 1.0.0
|
|
268
|
-
* @category
|
|
249
|
+
* @category Merging
|
|
269
250
|
*/
|
|
270
|
-
export
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
const handlersVariance = {
|
|
281
|
-
_Tools: identity
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
class HandlersImpl<Tools extends Tool.AnySchema, R = never> implements Handlers<Tools, R> {
|
|
285
|
-
readonly [HandlersTypeId]: Handlers.Variance<Tools>
|
|
286
|
-
constructor(
|
|
287
|
-
readonly toolkit: AiToolkit<Tools>,
|
|
288
|
-
readonly handlers: HashMap.HashMap<string, Tool.Handler<any, R>>
|
|
289
|
-
) {
|
|
290
|
-
this[HandlersTypeId] = handlersVariance
|
|
291
|
-
}
|
|
292
|
-
static fromToolkit<Tools extends Tool.AnySchema>(toolkit: AiToolkit<Tools>): Handlers<Tools> {
|
|
293
|
-
return new HandlersImpl(toolkit, HashMap.empty())
|
|
294
|
-
}
|
|
295
|
-
handle<Tag extends Types.Tags<Tools>, RH>(
|
|
296
|
-
tag: Tag,
|
|
297
|
-
f: Tool.Handler<Types.ExtractTag<Tools, Tag>, RH>
|
|
298
|
-
): Handlers<Types.ExcludeTag<Tools, Tag>, R | RH | Tool.Context<Types.ExtractTag<Tools, Tag>>> {
|
|
299
|
-
return new HandlersImpl(this.toolkit as any, HashMap.set(this.handlers, tag, f as any))
|
|
251
|
+
export const merge = <const Toolkits extends ReadonlyArray<Any>>(
|
|
252
|
+
...toolkits: Toolkits
|
|
253
|
+
): AiToolkit<Tools<Toolkits[number]>> => {
|
|
254
|
+
const tools = {} as Record<string, any>
|
|
255
|
+
for (const toolkit of toolkits) {
|
|
256
|
+
for (const [name, tool] of toolkit.tools) {
|
|
257
|
+
tools[name] = tool
|
|
258
|
+
}
|
|
300
259
|
}
|
|
260
|
+
return makeProto(tools) as any
|
|
301
261
|
}
|
package/src/Tokenizer.ts
CHANGED
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @since 1.0.0
|
|
3
3
|
*/
|
|
4
|
-
import * as Chunk from "effect/Chunk"
|
|
5
4
|
import * as Context from "effect/Context"
|
|
6
5
|
import * as Effect from "effect/Effect"
|
|
7
|
-
import * as
|
|
6
|
+
import * as Predicate from "effect/Predicate"
|
|
8
7
|
import type { AiError } from "./AiError.js"
|
|
9
|
-
import type { Message } from "./AiInput.js"
|
|
10
8
|
import * as AiInput from "./AiInput.js"
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
11
|
* @since 1.0.0
|
|
14
|
-
* @category
|
|
12
|
+
* @category Tags
|
|
15
13
|
*/
|
|
16
14
|
export class Tokenizer extends Context.Tag("@effect/ai/Tokenizer")<
|
|
17
15
|
Tokenizer,
|
|
@@ -20,22 +18,21 @@ export class Tokenizer extends Context.Tag("@effect/ai/Tokenizer")<
|
|
|
20
18
|
|
|
21
19
|
/**
|
|
22
20
|
* @since 1.0.0
|
|
23
|
-
* @category models
|
|
24
21
|
*/
|
|
25
22
|
export declare namespace Tokenizer {
|
|
26
23
|
/**
|
|
27
24
|
* @since 1.0.0
|
|
28
|
-
* @
|
|
25
|
+
* @category Models
|
|
29
26
|
*/
|
|
30
27
|
export interface Service {
|
|
31
|
-
readonly tokenize: (
|
|
32
|
-
readonly truncate: (
|
|
28
|
+
readonly tokenize: (input: AiInput.Raw) => Effect.Effect<Array<number>, AiError>
|
|
29
|
+
readonly truncate: (input: AiInput.Raw, tokens: number) => Effect.Effect<AiInput.AiInput, AiError>
|
|
33
30
|
}
|
|
34
31
|
}
|
|
35
32
|
|
|
36
33
|
/**
|
|
37
34
|
* @since 1.0.0
|
|
38
|
-
* @category
|
|
35
|
+
* @category Constructors
|
|
39
36
|
*/
|
|
40
37
|
export const make = (options: {
|
|
41
38
|
readonly tokenize: (content: AiInput.AiInput) => Effect.Effect<Array<number>, AiError>
|
|
@@ -44,33 +41,32 @@ export const make = (options: {
|
|
|
44
41
|
tokenize(input) {
|
|
45
42
|
return options.tokenize(AiInput.make(input))
|
|
46
43
|
},
|
|
47
|
-
truncate(
|
|
48
|
-
return truncate(AiInput.make(
|
|
44
|
+
truncate(input, tokens) {
|
|
45
|
+
return truncate(AiInput.make(input), options.tokenize, tokens)
|
|
49
46
|
}
|
|
50
47
|
})
|
|
51
48
|
|
|
52
49
|
const truncate = (
|
|
53
50
|
self: AiInput.AiInput,
|
|
54
|
-
tokenize: (
|
|
51
|
+
tokenize: (input: AiInput.AiInput) => Effect.Effect<Array<number>, AiError>,
|
|
55
52
|
maxTokens: number
|
|
56
53
|
): Effect.Effect<AiInput.AiInput, AiError> =>
|
|
57
54
|
Effect.suspend(() => {
|
|
58
55
|
let count = 0
|
|
59
|
-
let
|
|
60
|
-
let
|
|
56
|
+
let inputMessages = self.messages
|
|
57
|
+
let outputMessages: Array<AiInput.Message> = []
|
|
61
58
|
const loop: Effect.Effect<AiInput.AiInput, AiError> = Effect.suspend(() => {
|
|
62
|
-
const
|
|
63
|
-
if (
|
|
64
|
-
return Effect.succeed(AiInput.make(
|
|
59
|
+
const message = inputMessages[inputMessages.length - 1]
|
|
60
|
+
if (Predicate.isUndefined(message)) {
|
|
61
|
+
return Effect.succeed(AiInput.make(outputMessages))
|
|
65
62
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return Effect.flatMap(tokenize(Chunk.of(part)), (tokens) => {
|
|
63
|
+
inputMessages = inputMessages.slice(0, inputMessages.length - 1)
|
|
64
|
+
return Effect.flatMap(tokenize(AiInput.make(message)), (tokens) => {
|
|
69
65
|
count += tokens.length
|
|
70
66
|
if (count > maxTokens) {
|
|
71
|
-
return Effect.succeed(AiInput.make(
|
|
67
|
+
return Effect.succeed(AiInput.make(outputMessages))
|
|
72
68
|
}
|
|
73
|
-
|
|
69
|
+
outputMessages = [message, ...outputMessages]
|
|
74
70
|
return loop
|
|
75
71
|
})
|
|
76
72
|
})
|
package/src/index.ts
CHANGED
|
@@ -6,37 +6,37 @@ export * as AiChat from "./AiChat.js"
|
|
|
6
6
|
/**
|
|
7
7
|
* @since 1.0.0
|
|
8
8
|
*/
|
|
9
|
-
export * as
|
|
9
|
+
export * as AiEmbeddingModel from "./AiEmbeddingModel.js"
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* @since 1.0.0
|
|
13
13
|
*/
|
|
14
|
-
export * as
|
|
14
|
+
export * as AiError from "./AiError.js"
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* @since 1.0.0
|
|
18
18
|
*/
|
|
19
|
-
export * as
|
|
19
|
+
export * as AiInput from "./AiInput.js"
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
22
|
* @since 1.0.0
|
|
23
23
|
*/
|
|
24
|
-
export * as
|
|
24
|
+
export * as AiLanguageModel from "./AiLanguageModel.js"
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* @since 1.0.0
|
|
28
28
|
*/
|
|
29
|
-
export * as
|
|
29
|
+
export * as AiModel from "./AiModel.js"
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* @since 1.0.0
|
|
33
33
|
*/
|
|
34
|
-
export * as
|
|
34
|
+
export * as AiPlan from "./AiPlan.js"
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
37
|
* @since 1.0.0
|
|
38
38
|
*/
|
|
39
|
-
export * as
|
|
39
|
+
export * as AiResponse from "./AiResponse.js"
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* @since 1.0.0
|
|
@@ -46,17 +46,12 @@ export * as AiTelemetry from "./AiTelemetry.js"
|
|
|
46
46
|
/**
|
|
47
47
|
* @since 1.0.0
|
|
48
48
|
*/
|
|
49
|
-
export * as
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* @since 1.0.0
|
|
53
|
-
*/
|
|
54
|
-
export * as Completions from "./Completions.js"
|
|
49
|
+
export * as AiTool from "./AiTool.js"
|
|
55
50
|
|
|
56
51
|
/**
|
|
57
52
|
* @since 1.0.0
|
|
58
53
|
*/
|
|
59
|
-
export * as
|
|
54
|
+
export * as AiToolkit from "./AiToolkit.js"
|
|
60
55
|
|
|
61
56
|
/**
|
|
62
57
|
* @since 1.0.0
|