import { BaseEmbedding } from "../embeddings/types.js";
import { Ollama as OllamaBase } from "../internal/deps/ollama.js";
import { extractText, streamConverter } from "./utils.js";
const messageAccessor = (part)=>{
    return {
        raw: part,
        delta: part.message.content
    };
};
const completionAccessor = (part)=>{
    return {
        text: part.response,
        raw: part
    };
};
/**
 * This class both implements the LLM and Embedding interfaces.
 */ export class Ollama extends BaseEmbedding {
    hasStreaming = true;
    ollama;
    // https://ollama.ai/library
    model;
    options = {
        num_ctx: 4096,
        top_p: 0.9,
        temperature: 0.7
    };
    constructor(params){
        super();
        this.model = params.model;
        this.ollama = new OllamaBase(params.config);
        if (params.options) {
            this.options = {
                ...this.options,
                ...params.options
            };
        }
    }
    get metadata() {
        const { temperature, top_p, num_ctx } = this.options;
        return {
            model: this.model,
            temperature: temperature,
            topP: top_p,
            maxTokens: undefined,
            contextWindow: num_ctx,
            tokenizer: undefined
        };
    }
    async chat(params) {
        const { messages, stream } = params;
        const payload = {
            model: this.model,
            messages: messages.map((message)=>({
                    role: message.role,
                    content: extractText(message.content)
                })),
            stream: !!stream,
            options: {
                ...this.options
            }
        };
        if (!stream) {
            const chatResponse = await this.ollama.chat({
                ...payload,
                stream: false
            });
            return {
                message: {
                    role: "assistant",
                    content: chatResponse.message.content
                },
                raw: chatResponse
            };
        } else {
            const stream = await this.ollama.chat({
                ...payload,
                stream: true
            });
            return streamConverter(stream, messageAccessor);
        }
    }
    async complete(params) {
        const { prompt, stream } = params;
        const payload = {
            model: this.model,
            prompt: extractText(prompt),
            stream: !!stream,
            options: {
                ...this.options
            }
        };
        if (!stream) {
            const response = await this.ollama.generate({
                ...payload,
                stream: false
            });
            return {
                text: response.response,
                raw: response
            };
        } else {
            const stream = await this.ollama.generate({
                ...payload,
                stream: true
            });
            return streamConverter(stream, completionAccessor);
        }
    }
    async getEmbedding(prompt) {
        const payload = {
            model: this.model,
            prompt,
            options: {
                ...this.options
            }
        };
        const response = await this.ollama.embeddings({
            ...payload
        });
        return response.embedding;
    }
    async getTextEmbedding(text) {
        return this.getEmbedding(text);
    }
    push(request) {
        return this.ollama.push(request);
    }
    abort() {
        return this.ollama.abort();
    }
    encodeImage(image) {
        return this.ollama.encodeImage(image);
    }
    generate(request) {
        return this.ollama.generate(request);
    }
    create(request) {
        return this.ollama.create(request);
    }
    pull(request) {
        return this.ollama.pull(request);
    }
    delete(request) {
        return this.ollama.delete(request);
    }
    copy(request) {
        return this.ollama.copy(request);
    }
    list() {
        return this.ollama.list();
    }
    show(request) {
        return this.ollama.show(request);
    }
    embeddings(request) {
        return this.ollama.embeddings(request);
    }
}
