add default script
This commit is contained in:
parent
aa4cf681a9
commit
02b7367b4e
3 changed files with 78 additions and 30 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
import type { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3FinishReason } from "@ai-sdk/provider"
|
import type { LanguageModelV3, LanguageModelV3CallOptions, LanguageModelV3FinishReason, LanguageModelV3StreamPart } from "@ai-sdk/provider"
|
||||||
|
import { simulateReadableStream } from "ai"
|
||||||
import { Effect, Layer } from "effect"
|
import { Effect, Layer } from "effect"
|
||||||
import { Provider } from "@/provider/provider"
|
import { Provider } from "@/provider/provider"
|
||||||
import { ModelID, ProviderID } from "@/provider/schema"
|
import { ModelID, ProviderID } from "@/provider/schema"
|
||||||
|
|
@ -39,6 +40,15 @@ const provider: Provider.Info = {
|
||||||
models: { [modelID]: model },
|
models: { [modelID]: model },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultScript: LLMScript = {
|
||||||
|
steps: [[{ type: "text", content: "Simulation mock response." }]],
|
||||||
|
finish: "stop",
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextScript(simulation: Simulation.Interface) {
|
||||||
|
return Effect.runPromise(simulation.nextLLM().pipe(Effect.catch(() => Effect.succeed(defaultScript))))
|
||||||
|
}
|
||||||
|
|
||||||
function text(script: LLMScript) {
|
function text(script: LLMScript) {
|
||||||
return script.steps[0]?.flatMap((item) => (item.type === "text" || item.type === "thinking" ? [item.content] : []))
|
return script.steps[0]?.flatMap((item) => (item.type === "text" || item.type === "thinking" ? [item.content] : []))
|
||||||
.join("") ?? ""
|
.join("") ?? ""
|
||||||
|
|
@ -49,31 +59,33 @@ function error(script: LLMScript) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function stream(script: LLMScript) {
|
function stream(script: LLMScript) {
|
||||||
return new ReadableStream({
|
const chunks: LanguageModelV3StreamPart[] = [{ type: "stream-start", warnings: [] }]
|
||||||
start(controller) {
|
for (const [index, item] of (script.steps[0] ?? []).entries()) {
|
||||||
controller.enqueue({ type: "stream-start", warnings: [] })
|
if (item.type === "error") {
|
||||||
let index = 0
|
chunks.push({ type: "error", error: new Error(item.message) })
|
||||||
for (const item of script.steps[0] ?? []) {
|
continue
|
||||||
index++
|
}
|
||||||
if (item.type === "error") {
|
const id = `simulation-${item.type}-${index + 1}`
|
||||||
controller.enqueue({ type: "error", error: new Error(item.message) })
|
if (item.type === "thinking") {
|
||||||
controller.close()
|
chunks.push(
|
||||||
return
|
{ type: "reasoning-start", id },
|
||||||
}
|
{ type: "reasoning-delta", id, delta: item.content },
|
||||||
const id = `simulation-${item.type}-${index}`
|
{ type: "reasoning-end", id },
|
||||||
if (item.type === "thinking") {
|
)
|
||||||
controller.enqueue({ type: "reasoning-start", id })
|
continue
|
||||||
controller.enqueue({ type: "reasoning-delta", id, delta: item.content })
|
}
|
||||||
controller.enqueue({ type: "reasoning-end", id })
|
chunks.push(
|
||||||
continue
|
{ type: "text-start", id },
|
||||||
}
|
{ type: "text-delta", id, delta: item.content },
|
||||||
controller.enqueue({ type: "text-start", id })
|
{ type: "text-end", id },
|
||||||
controller.enqueue({ type: "text-delta", id, delta: item.content })
|
)
|
||||||
controller.enqueue({ type: "text-end", id })
|
}
|
||||||
}
|
chunks.push({ type: "finish", finishReason: finishReason(script), usage: usage(script) })
|
||||||
controller.enqueue({ type: "finish", finishReason: finishReason(script), usage: usage(script) })
|
|
||||||
controller.close()
|
return simulateReadableStream({
|
||||||
},
|
chunks,
|
||||||
|
initialDelayInMs: 0,
|
||||||
|
chunkDelayInMs: 0,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +117,7 @@ function language(simulation: Simulation.Interface): LanguageModelV3 {
|
||||||
modelId: modelID,
|
modelId: modelID,
|
||||||
supportedUrls: {},
|
supportedUrls: {},
|
||||||
async doGenerate(_options: LanguageModelV3CallOptions) {
|
async doGenerate(_options: LanguageModelV3CallOptions) {
|
||||||
const script = await Effect.runPromise(simulation.nextLLM())
|
const script = await nextScript(simulation)
|
||||||
const err = error(script)
|
const err = error(script)
|
||||||
if (err?.type === "error") throw new Error(err.message)
|
if (err?.type === "error") throw new Error(err.message)
|
||||||
return {
|
return {
|
||||||
|
|
@ -116,7 +128,7 @@ function language(simulation: Simulation.Interface): LanguageModelV3 {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async doStream(_options: LanguageModelV3CallOptions) {
|
async doStream(_options: LanguageModelV3CallOptions) {
|
||||||
const script = await Effect.runPromise(simulation.nextLLM())
|
const script = await nextScript(simulation)
|
||||||
return { stream: stream(script) }
|
return { stream: stream(script) }
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -108,11 +108,17 @@ export const layer = Layer.effect(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const fs = yield* AppFileSystem.Service
|
const fs = yield* AppFileSystem.Service
|
||||||
const network = yield* SimulationNetwork.Service
|
const network = yield* SimulationNetwork.Service
|
||||||
const state = yield* Ref.make<State>({ files: [], networkRegistrations: [], llmScripts: [], consumedLLMScripts: 0 })
|
const empty: State = {
|
||||||
|
files: [],
|
||||||
|
networkRegistrations: [],
|
||||||
|
llmScripts: [],
|
||||||
|
consumedLLMScripts: 0,
|
||||||
|
}
|
||||||
|
const state = yield* Ref.make<State>(empty)
|
||||||
|
|
||||||
const reset = Effect.fn("Simulation.reset")(function* () {
|
const reset = Effect.fn("Simulation.reset")(function* () {
|
||||||
yield* network.reset()
|
yield* network.reset()
|
||||||
yield* Ref.set(state, { files: [], networkRegistrations: [], llmScripts: [], consumedLLMScripts: 0 })
|
yield* Ref.set(state, empty)
|
||||||
})
|
})
|
||||||
|
|
||||||
const seedFilesystem = Effect.fn("Simulation.seedFilesystem")(function* (input: typeof FilesystemSeedInput.Type) {
|
const seedFilesystem = Effect.fn("Simulation.seedFilesystem")(function* (input: typeof FilesystemSeedInput.Type) {
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,36 @@ describe("Simulation", () => {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it.effect("simulation provider returns a default response when no script is queued", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const provider = yield* Provider.Service
|
||||||
|
const model = yield* provider.defaultModel().pipe(Effect.flatMap((item) => provider.getModel(item.providerID, item.modelID)))
|
||||||
|
const language = yield* provider.getLanguage(model)
|
||||||
|
|
||||||
|
const result = yield* Effect.promise(() => language.doGenerate({ prompt: [], abortSignal: undefined }))
|
||||||
|
expect(result.content).toEqual([{ type: "text", text: "Simulation mock response." }])
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
it.effect("simulation provider streams a default response when no script is queued", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
const provider = yield* Provider.Service
|
||||||
|
const model = yield* provider.defaultModel().pipe(Effect.flatMap((item) => provider.getModel(item.providerID, item.modelID)))
|
||||||
|
const language = yield* provider.getLanguage(model)
|
||||||
|
|
||||||
|
const result = yield* Effect.promise(() => language.doStream({ prompt: [], abortSignal: undefined }))
|
||||||
|
const reader = result.stream.getReader()
|
||||||
|
const parts: unknown[] = []
|
||||||
|
while (true) {
|
||||||
|
const next = yield* Effect.promise(() => reader.read())
|
||||||
|
if (next.done) break
|
||||||
|
parts.push(next.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parts).toContainEqual({ type: "text-delta", id: "simulation-text-1", delta: "Simulation mock response." })
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.effect("simulation provider streams queued script actions", () =>
|
it.effect("simulation provider streams queued script actions", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const simulation = yield* Simulation.Service
|
const simulation = yield* Simulation.Service
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue