import { __exportAll } from "../_virtual/_rolldown/runtime.js";
import { callbackHandlerPrefersStreaming } from "../callbacks/base.js";
import { CallbackManager } from "../callbacks/manager.js";
import { concat } from "../utils/stream.js";
import { GenerationChunk, RUN_KEY } from "../outputs.js";
import { BaseLanguageModel } from "./base.js";
//#region src/language_models/llms.ts
var llms_exports = /* @__PURE__ */ __exportAll({
	BaseLLM: () => BaseLLM,
	LLM: () => LLM
});
/**
* LLM Wrapper. Takes in a prompt (or prompts) and returns a string.
*/
var BaseLLM = class BaseLLM extends BaseLanguageModel {
	lc_namespace = [
		"langchain",
		"llms",
		this._llmType()
	];
	/**
	* This method takes an input and options, and returns a string. It
	* converts the input to a prompt value and generates a result based on
	* the prompt.
	* @param input Input for the LLM.
	* @param options Options for the LLM call.
	* @returns A string result based on the prompt.
	*/
	async invoke(input, options) {
		const promptValue = BaseLLM._convertInputToPromptValue(input);
		return (await this.generatePrompt([promptValue], options, options?.callbacks)).generations[0][0].text;
	}
	async *_streamResponseChunks(_input, _options, _runManager) {
		throw new Error("Not implemented.");
	}
	_separateRunnableConfigFromCallOptionsCompat(options) {
		const [runnableConfig, callOptions] = super._separateRunnableConfigFromCallOptions(options);
		callOptions.signal = runnableConfig.signal;
		return [runnableConfig, callOptions];
	}
	async *_streamIterator(input, options) {
		if (this._streamResponseChunks === BaseLLM.prototype._streamResponseChunks) yield this.invoke(input, options);
		else {
			const prompt = BaseLLM._convertInputToPromptValue(input);
			const [runnableConfig, callOptions] = this._separateRunnableConfigFromCallOptionsCompat(options);
			const invocationParams = this.invocationParams(callOptions);
			const callbackManager_ = await CallbackManager.configure(runnableConfig.callbacks, this.callbacks, runnableConfig.tags, this.tags, runnableConfig.metadata, this.metadata, {
				verbose: this.verbose,
				tracerInheritableMetadata: this._filterInvocationParamsForTracing(invocationParams)
			});
			const extra = {
				options: callOptions,
				invocation_params: invocationParams,
				batch_size: 1
			};
			const runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), [prompt.toString()], runnableConfig.runId, void 0, extra, void 0, void 0, runnableConfig.runName);
			let generation = new GenerationChunk({ text: "" });
			try {
				for await (const chunk of this._streamResponseChunks(prompt.toString(), callOptions, runManagers?.[0])) {
					if (!generation) generation = chunk;
					else generation = generation.concat(chunk);
					if (typeof chunk.text === "string") yield chunk.text;
				}
			} catch (err) {
				await Promise.all((runManagers ?? []).map((runManager) => runManager?.handleLLMError(err)));
				throw err;
			}
			await Promise.all((runManagers ?? []).map((runManager) => runManager?.handleLLMEnd({ generations: [[generation]] })));
		}
	}
	/**
	* This method takes prompt values, options, and callbacks, and generates
	* a result based on the prompts.
	* @param promptValues Prompt values for the LLM.
	* @param options Options for the LLM call.
	* @param callbacks Callbacks for the LLM call.
	* @returns An LLMResult based on the prompts.
	*/
	async generatePrompt(promptValues, options, callbacks) {
		const prompts = promptValues.map((promptValue) => promptValue.toString());
		return this.generate(prompts, options, callbacks);
	}
	/**
	* Get the parameters used to invoke the model
	*/
	invocationParams(_options) {
		return {};
	}
	_flattenLLMResult(llmResult) {
		const llmResults = [];
		for (let i = 0; i < llmResult.generations.length; i += 1) {
			const genList = llmResult.generations[i];
			if (i === 0) llmResults.push({
				generations: [genList],
				llmOutput: llmResult.llmOutput
			});
			else {
				const llmOutput = llmResult.llmOutput ? {
					...llmResult.llmOutput,
					tokenUsage: {}
				} : void 0;
				llmResults.push({
					generations: [genList],
					llmOutput
				});
			}
		}
		return llmResults;
	}
	/** @ignore */
	async _generateUncached(prompts, parsedOptions, handledOptions, startedRunManagers) {
		let runManagers;
		if (startedRunManagers !== void 0 && startedRunManagers.length === prompts.length) runManagers = startedRunManagers;
		else {
			const invocationParams = this.invocationParams(parsedOptions);
			const callbackManager_ = await CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, handledOptions.metadata, this.metadata, {
				verbose: this.verbose,
				tracerInheritableMetadata: this._filterInvocationParamsForTracing(invocationParams)
			});
			const extra = {
				options: parsedOptions,
				invocation_params: invocationParams,
				batch_size: prompts.length
			};
			runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, handledOptions.runId, void 0, extra, void 0, void 0, handledOptions?.runName);
		}
		const hasStreamingHandler = !!runManagers?.[0].handlers.find(callbackHandlerPrefersStreaming);
		let output;
		if (hasStreamingHandler && prompts.length === 1 && this._streamResponseChunks !== BaseLLM.prototype._streamResponseChunks) try {
			const stream = await this._streamResponseChunks(prompts[0], parsedOptions, runManagers?.[0]);
			let aggregated;
			for await (const chunk of stream) if (aggregated === void 0) aggregated = chunk;
			else aggregated = concat(aggregated, chunk);
			if (aggregated === void 0) throw new Error("Received empty response from chat model call.");
			output = {
				generations: [[aggregated]],
				llmOutput: {}
			};
			await runManagers?.[0].handleLLMEnd(output);
		} catch (e) {
			await runManagers?.[0].handleLLMError(e);
			throw e;
		}
		else {
			try {
				output = await this._generate(prompts, parsedOptions, runManagers?.[0]);
			} catch (err) {
				await Promise.all((runManagers ?? []).map((runManager) => runManager?.handleLLMError(err)));
				throw err;
			}
			const flattenedOutputs = this._flattenLLMResult(output);
			await Promise.all((runManagers ?? []).map((runManager, i) => runManager?.handleLLMEnd(flattenedOutputs[i])));
		}
		const runIds = runManagers?.map((manager) => manager.runId) || void 0;
		Object.defineProperty(output, RUN_KEY, {
			value: runIds ? { runIds } : void 0,
			configurable: true
		});
		return output;
	}
	async _generateCached({ prompts, cache, llmStringKey, parsedOptions, handledOptions, runId }) {
		const invocationParams = this.invocationParams(parsedOptions);
		const callbackManager_ = await CallbackManager.configure(handledOptions.callbacks, this.callbacks, handledOptions.tags, this.tags, handledOptions.metadata, this.metadata, {
			verbose: this.verbose,
			tracerInheritableMetadata: this._filterInvocationParamsForTracing(invocationParams)
		});
		const extra = {
			options: parsedOptions,
			invocation_params: invocationParams,
			batch_size: prompts.length
		};
		const runManagers = await callbackManager_?.handleLLMStart(this.toJSON(), prompts, runId, void 0, extra, void 0, void 0, handledOptions?.runName);
		const missingPromptIndices = [];
		const cachedResults = (await Promise.allSettled(prompts.map(async (prompt, index) => {
			const result = await cache.lookup(prompt, llmStringKey);
			if (result == null) missingPromptIndices.push(index);
			return result;
		}))).map((result, index) => ({
			result,
			runManager: runManagers?.[index]
		})).filter(({ result }) => result.status === "fulfilled" && result.value != null || result.status === "rejected");
		const generations = [];
		await Promise.all(cachedResults.map(async ({ result: promiseResult, runManager }, i) => {
			if (promiseResult.status === "fulfilled") {
				const result = promiseResult.value;
				generations[i] = result.map((result) => {
					result.generationInfo = {
						...result.generationInfo,
						tokenUsage: {}
					};
					return result;
				});
				if (result.length) await runManager?.handleLLMNewToken(result[0].text);
				return runManager?.handleLLMEnd({ generations: [result] }, void 0, void 0, void 0, { cached: true });
			} else {
				await runManager?.handleLLMError(promiseResult.reason, void 0, void 0, void 0, { cached: true });
				return Promise.reject(promiseResult.reason);
			}
		}));
		const output = {
			generations,
			missingPromptIndices,
			startedRunManagers: runManagers
		};
		Object.defineProperty(output, RUN_KEY, {
			value: runManagers ? { runIds: runManagers?.map((manager) => manager.runId) } : void 0,
			configurable: true
		});
		return output;
	}
	/**
	* Run the LLM on the given prompts and input, handling caching.
	*/
	async generate(prompts, options, callbacks) {
		if (!Array.isArray(prompts)) throw new Error("Argument 'prompts' is expected to be a string[]");
		let parsedOptions;
		if (Array.isArray(options)) parsedOptions = { stop: options };
		else parsedOptions = options;
		const [runnableConfig, callOptions] = this._separateRunnableConfigFromCallOptionsCompat(parsedOptions);
		runnableConfig.callbacks = runnableConfig.callbacks ?? callbacks;
		if (!this.cache) return this._generateUncached(prompts, callOptions, runnableConfig);
		const { cache } = this;
		const llmStringKey = this._getSerializedCacheKeyParametersForCall(callOptions);
		const { generations, missingPromptIndices, startedRunManagers } = await this._generateCached({
			prompts,
			cache,
			llmStringKey,
			parsedOptions: callOptions,
			handledOptions: runnableConfig,
			runId: runnableConfig.runId
		});
		let llmOutput = {};
		if (missingPromptIndices.length > 0) {
			const results = await this._generateUncached(missingPromptIndices.map((i) => prompts[i]), callOptions, runnableConfig, startedRunManagers !== void 0 ? missingPromptIndices.map((i) => startedRunManagers?.[i]) : void 0);
			await Promise.all(results.generations.map(async (generation, index) => {
				const promptIndex = missingPromptIndices[index];
				generations[promptIndex] = generation;
				return cache.update(prompts[promptIndex], llmStringKey, generation);
			}));
			llmOutput = results.llmOutput ?? {};
		}
		return {
			generations,
			llmOutput
		};
	}
	/**
	* Get the identifying parameters of the LLM.
	*/
	_identifyingParams() {
		return {};
	}
	_modelType() {
		return "base_llm";
	}
};
/**
* LLM class that provides a simpler interface to subclass than {@link BaseLLM}.
*
* Requires only implementing a simpler {@link _call} method instead of {@link _generate}.
*
* @augments BaseLLM
*/
var LLM = class extends BaseLLM {
	async _generate(prompts, options, runManager) {
		return { generations: await Promise.all(prompts.map((prompt, promptIndex) => this._call(prompt, {
			...options,
			promptIndex
		}, runManager).then((text) => [{ text }]))) };
	}
};
//#endregion
export { BaseLLM, LLM, llms_exports };

//# sourceMappingURL=llms.js.map