From 8cdeacaad8ec66ddc7b6efb2a700c043ddf8d30c Mon Sep 17 00:00:00 2001
From: Milkey Tan <24996957+mili-tan@users.noreply.github.com>
Date: Sun, 5 Jan 2025 20:06:17 +0800
Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?=
=?UTF-8?q?=E4=BB=B6=E3=80=82?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
Onllama.MondrianGateway.csproj | 17 ++++
Onllama.MondrianGateway.sln | 22 +++++
Program.cs | 165 +++++++++++++++++++++++++++++++++
3 files changed, 204 insertions(+)
create mode 100644 Onllama.MondrianGateway.csproj
create mode 100644 Onllama.MondrianGateway.sln
create mode 100644 Program.cs
diff --git a/Onllama.MondrianGateway.csproj b/Onllama.MondrianGateway.csproj
new file mode 100644
index 0000000..a1e28a8
--- /dev/null
+++ b/Onllama.MondrianGateway.csproj
@@ -0,0 +1,17 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
diff --git a/Onllama.MondrianGateway.sln b/Onllama.MondrianGateway.sln
new file mode 100644
index 0000000..c2581cd
--- /dev/null
+++ b/Onllama.MondrianGateway.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.12.35527.113 d17.12
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Onllama.MondrianGateway", "Onllama.MondrianGateway.csproj", "{A02922EF-22BD-4526-A6E3-3A5C7B20E618}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {A02922EF-22BD-4526-A6E3-3A5C7B20E618}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {A02922EF-22BD-4526-A6E3-3A5C7B20E618}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {A02922EF-22BD-4526-A6E3-3A5C7B20E618}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {A02922EF-22BD-4526-A6E3-3A5C7B20E618}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Program.cs b/Program.cs
new file mode 100644
index 0000000..b1664f4
--- /dev/null
+++ b/Program.cs
@@ -0,0 +1,165 @@
+using System.Net;
+using System.Text;
+using Microsoft.AspNetCore.Builder;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Routing;
+using Microsoft.AspNetCore.Server.Kestrel.Core;
+using Microsoft.Extensions.DependencyInjection;
+using Newtonsoft.Json.Linq;
+using OllamaSharp;
+using OllamaSharp.Models.Chat;
+using ProxyKit;
+
+
+namespace Onllama.MondrianGateway
+{
+ internal class Program
+ {
+ static void Main(string[] args)
+ {
+ try
+ {
+ var ollama = new OllamaApiClient(new Uri("http://localhost:11434"));
+ var paths = new List
+ {
+ "/api/generate", "/api/chat", "/api/tags", "/api/embed", "/api/show", "/api/ps", "/api/embeddings"
+ };
+
+ var host = new WebHostBuilder()
+ .UseKestrel()
+ .UseContentRoot(AppDomain.CurrentDomain.SetupInformation.ApplicationBase)
+ .ConfigureServices(services =>
+ {
+ services.AddRouting();
+ services.AddProxy(httpClientBuilder =>
+ httpClientBuilder.ConfigureHttpClient(client =>
+ client.Timeout = TimeSpan.FromMinutes(5)));
+ })
+ .ConfigureKestrel(options =>
+ {
+ options.ListenAnyIP(18080,
+ listenOptions => listenOptions.Protocols = HttpProtocols.Http1AndHttp2);
+ })
+ .Configure(app =>
+ {
+ app.Use(async (context, next) =>
+ {
+ var token = context.Request.Headers.ContainsKey("Authorization")
+ ? context.Request.Headers.Authorization.ToString().Split(' ').Last().ToString()
+ : string.Empty;
+ //if (token != "sk-")
+ if (false)
+ {
+ context.Response.Headers.ContentType = "application/json";
+ context.Response.StatusCode = (int) HttpStatusCode.Forbidden;
+ await context.Response.WriteAsync(new JObject()
+ {
+ {
+ "error", new JObject()
+ {
+ {
+ "message",
+ "Authentication Fails, You need to provide a valid API key in the Authorization header using Bearer authentication (i.e. Authorization: Bearer YOUR_KEY)."
+ },
+ {"type", "invalid_request_error"}
+ }
+ }
+ }.ToString());
+ }
+ else
+ {
+ context.Items["Token"] = token;
+ await next.Invoke();
+ }
+ });
+
+ foreach (var path in paths)
+ app.Map(path, svr =>
+ {
+ svr.RunProxy(async context =>
+ {
+ var response = new HttpResponseMessage();
+ try
+ {
+ response = await context.ForwardTo(new Uri("http://127.0.0.1:11434" + path))
+ .Send();
+ response.Headers.Add("X-Forwarder-By", "MondrianGateway/0.1");
+ return response;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ return response;
+ }
+ });
+ });
+
+ app.Map("/v1", svr =>
+ {
+ svr.RunProxy(async context =>
+ {
+ HttpResponseMessage response;
+ try
+ {
+ if (context.Request.Method.ToUpper() == "POST")
+ {
+ var body = await new StreamReader(context.Request.Body).ReadToEndAsync();
+ var jBody = JObject.Parse(body);
+
+ if (jBody["model"]?.ToString() == "gpt-3.5-turbo") jBody["model"] = "qwen2.5:7b";
+ Console.WriteLine(jBody.ToString());
+
+ var msgs = jBody["messages"]?.ToObject>();
+ await foreach (var res in ollama.ChatAsync(new ChatRequest()
+ {Model = "shieldgemma:2b", Messages = msgs, Stream = false}))
+ {
+ Console.WriteLine(res?.Message.Content);
+ var risks = res?.Message.Content?.ToLower();
+ if (risks != null && (risks.Contains("yes") || risks.Contains("unsafe")))
+ {
+ return new HttpResponseMessage(HttpStatusCode.UnavailableForLegalReasons)
+ {
+ Content = new StringContent(new JObject()
+ {
+ {
+ "error", new JObject()
+ {
+ {"message", "Messages with content security risks. Unable to continue."},
+ {"type", "content_risks"},
+ {"risk_model", res?.Model},
+ {"risk_raw_msg", res?.Message.Content}
+ }
+ }
+ }.ToString())
+ };
+ }
+ }
+
+ context.Request.Body = new MemoryStream(Encoding.UTF8.GetBytes(jBody.ToString()));
+ context.Request.ContentLength = context.Request.Body.Length;
+ }
+
+ response = await context.ForwardTo(new Uri("http://127.0.0.1:11434/v1")).Send();
+ response.Headers.Add("X-Forwarder-By", "MondrianGateway/0.1");
+ return response;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ response = await context.ForwardTo(new Uri("http://127.0.0.1:11434/v1")).Send();
+ return response;
+ }
+ });
+ });
+ }).Build();
+
+ host.Run();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+ }
+ }
+}