kernel-memory icon indicating copy to clipboard operation
kernel-memory copied to clipboard

how to post ChatHistory to kernel CreateFunctionFromPrompt in different way?

Open kill136 opened this issue 5 months ago • 3 comments

Context / Scenario

app.MapPost(Constants.HttpSKAskEndpoint,
    async Task (
        HttpContext context,
        SearchQuery query,
        IKernelMemory service,
        ILogger log,
        CancellationToken cancellationToken) =>
    {
        string apiKey = context.Request.Query["apiKey"];
        log.LogTrace("New skAsk request");
        IKernelBuilder builder = Kernel.CreateBuilder();
        builder.AddOpenAIChatCompletion(
            modelId: "gpt-3.5-turbo",
            apiKey: apiKey, null, serviceId: "chatgpt",
            new HttpClient() { BaseAddress = new Uri("https://www.barcodecloud.club/proxy/api.openai.com") });
        builder.Plugins.AddFromType();

        //var bingConnector = new BingConnector("...key...");
        //var bing = new WebSearchEnginePlugin(bingConnector);
        //builder. Plugins.AddFromObject(bing);
        //OpenAIClient? openAIClient = new OpenAIClient(apiKey,new OpenAIClientOptions() { Transport= }),
        //builder. Services.AddOpenAIChatCompletion("gpt-3.5-turbo", apiKey);

        var kernel = builder.Build();
        var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>("chatgpt");

        // Handler which is called before a function is invoked
        void MyInvokingHandler(object? sender, FunctionInvokingEventArgs e)
        {
            Console.WriteLine($"Invoking {e.Function.Name}");
        }

        // Handler which is called before a prompt is rendered
        void MyRenderingHandler(object? sender, PromptRenderingEventArgs e)
        {
            Console.WriteLine($"Rendering prompt for {e.Function.Name}");
        }

        // Handler which is called after a prompt is rendered
        void MyRenderedHandler(object? sender, PromptRenderedEventArgs e)
        {
            Console.WriteLine($"Rendered prompt: {e.RenderedPrompt}");
        }

        // Handler which is called after a function is invoked
        void MyInvokedHandler(object? sender, FunctionInvokedEventArgs e)
        {
            if (e.Result.Metadata is not null && e.Result.Metadata.ContainsKey("Usage"))
            {
                Console.WriteLine($"Token usage: {e.Result.Metadata?[" Usage"]?.AsJson()}");
            }
        }

        // Add the handlers to the kernel
        kernel.FunctionInvoking += MyInvokingHandler;
        kernel.PromptRendering += MyRenderingHandler;
        kernel.PromptRendered += MyRenderedHandler;
        kernel.FunctionInvoked += MyInvokedHandler;
        var skPrompt = """
                       客户提问: {{$input}}

                       知识库回答: {{memory.search $query}}

                       根据上面的信息,有感情的回答用户的提问,如果遇到你无法确认的信息,请自由调用插件功能,比如搜索引擎插件,时间插件
                       """;
        OpenAIPromptExecutionSettings settings = new() { ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions };
        var myFunction = kernel.CreateFunctionFromPrompt(skPrompt, settings);
        var memoryConnector = new MemoryWebClient("http://127.0.0.1:9001/", Environment.GetEnvironmentVariable("MEMORY_API_KEY"));
        var memoryPlugin = kernel.ImportPluginFromObject(new MemoryPlugin(memoryConnector, waitForIngestionToComplete: true), "memory");
        TagCollectionWrapper tags = new TagCollectionWrapper();

        foreach (var memoryFilter in query.Filters)
        {
            foreach (var filter in memoryFilter.GetFilters())
            {
                tags.Add(filter.Key, filter.Value);
            }
        }

        ChatHistory chatMessages = query.Messages;

        var answer = await myFunction.InvokeAsync(kernel, new KernelArguments()
        {
            { "input", query.Query },
            { "index", query.Index },
            { "query", query.Query },
            { "tags", tags },
            { "minRelevance", query.MinRelevance },
            { "limit", query.Limit }
        });
        Console.WriteLine("Answer: " + answer);
        return Results.Ok(answer.GetValue<string>());
    })
    .AddEndpointFilter(authFilter)
    .Produces<MemoryAnswer>(StatusCodes.Status200OK)
    .Produces<ProblemDetails>(StatusCodes.Status401Unauthorized)
    .Produces<ProblemDetails>(StatusCodes.Status403Forbidden);

The problem

####################################### above is my code, i dont want using {{$chatMessages }} para in a Prompt ,who knows other way?

Proposed solution

thanks

Importance

None

kill136 avatar Mar 04 '24 06:03 kill136