Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial implementation of Embedding data type. #1059

Open
wants to merge 47 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
5729d80
Initial implementation of Embedding data type.
Sep 5, 2024
6b3c965
Fix failing tests because OpenAI-DotNet.dll.
claudiamurialdo Sep 9, 2024
88e8656
Add OpenAI-DotNet to Unit test.
Sep 10, 2024
182c7b7
Add getGxembedding function.
Sep 10, 2024
69283a5
Add default constructor to GxEmbedding
Sep 10, 2024
77fdde6
Improve embedding methods.
Sep 11, 2024
3b4a929
Add missing parameter.
Sep 11, 2024
28fca72
Add messages parameter to GenerateEmbedding method
Sep 12, 2024
58f2cc2
Fix Message
Sep 12, 2024
b2be822
Improve embedding handling.
Sep 12, 2024
a8a8964
Add model and dimensions to database operations.
Sep 16, 2024
63d5e99
Apply configuration settings for OpenAI provider
Sep 17, 2024
7a70ca7
Fix Empty value for GxEmbedding.
Sep 18, 2024
f730c1f
The embedding model and dimensions were not set in the instance retur…
claudiamurialdo Oct 16, 2024
ffd749a
Migrate from OpenAI-DotNet to OpenAI api.
claudiamurialdo Nov 13, 2024
7cbdbc1
Refactor Embedding classes
claudiamurialdo Nov 14, 2024
bd1aaaf
Merge branch 'master' into embedding-data-type
claudiamurialdo Nov 14, 2024
c9114c4
Update Assistant interface
claudiamurialdo Nov 14, 2024
7a3f3a7
Minor code cleanups
claudiamurialdo Nov 14, 2024
504d406
Minor code cleanups
claudiamurialdo Nov 14, 2024
c15535b
Maintain implicit 'saia:agent:' prefix
claudiamurialdo Nov 14, 2024
d783a02
Make GXAgent public.
claudiamurialdo Nov 15, 2024
919c3ff
Change CallAssistant signature for result parameter (object).
claudiamurialdo Nov 15, 2024
f51076b
Add error handling for AgentObject.
claudiamurialdo Nov 15, 2024
22573c6
Add trace messages.
claudiamurialdo Nov 18, 2024
617a86e
Add CallResult.cs to .NETFramework standard classes
claudiamurialdo Nov 19, 2024
67b5b7b
Add missing file.
claudiamurialdo Nov 19, 2024
71f69e1
The EmbeddingService class must be public to allow dynamic creation f…
claudiamurialdo Nov 19, 2024
69d8b60
Add ChatMessage datatype.
claudiamurialdo Nov 25, 2024
09a1786
Change Namespace.
claudiamurialdo Nov 25, 2024
8f48ddf
Add CallAgent with chathistory parameter.
claudiamurialdo Nov 25, 2024
9748909
Implement CallAgent method.
claudiamurialdo Nov 25, 2024
e3a2eba
Convert chatMessages to openaichatmessages
claudiamurialdo Nov 27, 2024
bfaf671
Add missing null check.
claudiamurialdo Nov 27, 2024
b525b54
Handle exception when accessing an invalid chatCompetion.content.
claudiamurialdo Nov 27, 2024
c37bf0e
Replace OpenAI client with direct HttpClient call, as 'variables' is …
claudiamurialdo Nov 28, 2024
dbb369a
Remove unused classes and methods.
claudiamurialdo Nov 28, 2024
f692e68
Fix build error.
claudiamurialdo Nov 28, 2024
7e8efb2
Revert changes commited by mistake.
claudiamurialdo Nov 28, 2024
91f3b8b
Fix casing error.
claudiamurialdo Nov 29, 2024
b21653a
Move ProcessTollCall to GXAgent class in order to define CallTool vir…
claudiamurialdo Dec 12, 2024
831824e
Merge branch 'master' into embedding-data-type
claudiamurialdo Dec 13, 2024
5e7f23a
Fix id for finish reason tool_calls
claudiamurialdo Dec 13, 2024
c73d14e
Merge branch 'embedding-data-type' of https://github.com/genexuslabs/…
claudiamurialdo Dec 13, 2024
b94e7ff
minor
claudiamurialdo Dec 13, 2024
503806f
Fix failing test.
claudiamurialdo Dec 13, 2024
7e03762
"temporarily disabled" test
claudiamurialdo Dec 13, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions dotnet/DotNetStandardClasses.sln
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LogTest", "test\benchmarks\
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AccessTokenController_Test", "test\NativeAccessControllerTest\AccessTokenController_Test.csproj", "{A5589382-DB6F-4450-AE2B-6C6AA1643EF1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ai", "ai", "{D13691A9-04AE-4ABB-A694-8AD41D74CE23}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GxAI", "src\dotnetcore\Providers\AI\GxAI.csproj", "{88FE3199-CFE3-42C4-AD6F-3EE49D7B5998}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Functions", "Functions", "{E59B3248-4C26-4DB0-96CB-67437319E22B}"
EndProject
Global
Expand Down Expand Up @@ -643,6 +647,10 @@ Global
{A5589382-DB6F-4450-AE2B-6C6AA1643EF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5589382-DB6F-4450-AE2B-6C6AA1643EF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5589382-DB6F-4450-AE2B-6C6AA1643EF1}.Release|Any CPU.Build.0 = Release|Any CPU
{88FE3199-CFE3-42C4-AD6F-3EE49D7B5998}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88FE3199-CFE3-42C4-AD6F-3EE49D7B5998}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88FE3199-CFE3-42C4-AD6F-3EE49D7B5998}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88FE3199-CFE3-42C4-AD6F-3EE49D7B5998}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -769,6 +777,8 @@ Global
{46DAAFD1-FAF5-4904-8EC5-406BE04E5538} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC}
{A1DBDCE0-4F09-445F-A202-9B260CDD46CF} = {46DAAFD1-FAF5-4904-8EC5-406BE04E5538}
{A5589382-DB6F-4450-AE2B-6C6AA1643EF1} = {1D6F1776-FF4B-46C2-9B3D-BC46CCF049DC}
{D13691A9-04AE-4ABB-A694-8AD41D74CE23} = {2261B65E-3757-4E5B-9DCD-EAE8D1E236A3}
{88FE3199-CFE3-42C4-AD6F-3EE49D7B5998} = {D13691A9-04AE-4ABB-A694-8AD41D74CE23}
{E59B3248-4C26-4DB0-96CB-67437319E22B} = {41E1D031-799F-484F-85DE-7A30AF1A6FBA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
93 changes: 93 additions & 0 deletions dotnet/src/dotnetcore/GxClasses/Domain/GxEmbedding.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System;
using System.Threading.Tasks;
using GxClasses.Helpers;
namespace GeneXus.Utils
{
public class GxEmbedding
{

ReadOnlyMemory<float> _embedding;
public GxEmbedding()
{
}
public GxEmbedding(string model, int dimensions)
{
Model = model;
Dimensions = dimensions;
_embedding = new ReadOnlyMemory<float>(new float[dimensions]);
}
internal GxEmbedding(ReadOnlyMemory<float> embedding, string model, int dimensions) : this(model, dimensions)
{
_embedding = embedding;
}
internal GxEmbedding(float[] embedding)
{
_embedding = embedding;
}

internal static GxEmbedding Empty(string model, int dimensions)
{
return new GxEmbedding(model, dimensions);
}
public override string ToString()
{
return $"[{string.Join(",", _embedding.Span.ToArray())}]";
}
public static GxEmbedding GenerateEmbedding(GxEmbedding embeddingInfo, string text, GXBaseCollection<SdtMessages_Message> Messages)
{
try
{
ReadOnlyMemory<float> embedding = AIEmbeddingFactory.Instance.GenerateEmbeddingAsync(embeddingInfo.Model, embeddingInfo.Dimensions, text).GetAwaiter().GetResult();
return new GxEmbedding(embedding, embeddingInfo.Model, embeddingInfo.Dimensions);
}
catch (Exception ex)
{
GXUtil.ErrorToMessages("GenerateEmbedding Error", ex, Messages, false);
return embeddingInfo;
}
}
public string Model { get; set; }
public int Dimensions { get; set; }

internal ReadOnlyMemory<float> Data => _embedding;
}
internal interface IEmbeddingService
{
Task<ReadOnlyMemory<float>> GenerateEmbeddingAsync(string model, int dimensions, string input);
}
internal class AIEmbeddingFactory
{
private static readonly IGXLogger log = GXLoggerFactory.GetLogger<AIEmbeddingFactory>();

private static volatile IEmbeddingService instance;
private static object syncRoot = new object();
private const string AI_PROVIDER = "GeneXus.AI.EmbeddingService, GxAI, Version=10.1.0.0, Culture=neutral, PublicKeyToken=null";
public static IEmbeddingService Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{

try
{
Type type = AssemblyLoader.GetType(AI_PROVIDER);
instance = (IEmbeddingService)Activator.CreateInstance(type);
}
catch (Exception e)
{
GXLogging.Error(log, "Couldn't create AI Provider", e);
throw e;
}
}
}
}
return instance;
}
}
}
}
4 changes: 3 additions & 1 deletion dotnet/src/dotnetcore/GxClasses/GxClasses.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
<Compile Include="..\..\dotnetframework\GxClasses\Data\GXDataDb2400.cs" Link="Data\GXDataDb2400.cs" />
<Compile Include="..\..\dotnetframework\GxClasses\Diagnostics\Log.cs" Link="Diagnostics\Log.cs" />
<Compile Include="..\..\dotnetframework\GxClasses\Diagnostics\GXDebugManager.cs" Link="Diagnostics\GXDebugManager.cs" />
<Compile Include="..\..\dotnetframework\GxClasses\Domain\CallResult.cs" Link="Domain\CallResult.cs" />
<Compile Include="..\..\dotnetframework\GxClasses\Domain\ChatMessage.cs" Link="Domain\ChatMessage.cs" />
<Compile Include="..\..\dotnetframework\GxClasses\Domain\GXLDAP.cs" Link="Domain\GXLDAP.cs" />
<Compile Include="..\..\dotnetframework\GxClasses\Domain\GxMessages.cs" Link="Domain\GxMessages.cs" />
<Compile Include="..\..\dotnetframework\GxClasses\Domain\GxMessaging.cs" Link="Domain\GxMessaging.cs" />
Expand Down Expand Up @@ -162,13 +164,13 @@
<PackageReference Include="Azure.Monitor.OpenTelemetry.Exporter" Version="1.1.0" PrivateAssets="All" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.7.0" PrivateAssets="All" />
<PackageReference Include="OpenTelemetry.Exporter.Console" Version="1.7.0" PrivateAssets="All" />
<PackageReference Include="Pgvector" Version="0.3.0" PrivateAssets="All" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="8.0.0" />
<PackageReference Include="Microsoft.Win32.Registry" Version="4.7.0" />
<PackageReference Include="MySqlConnector" Version="2.2.3" PrivateAssets="All"/>
<PackageReference Include="NetTopologySuite" Version="2.0.0" />
<PackageReference Include="NodaTime" Version="3.1.9" />
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="3.3.1" />
<PackageReference Include="Npgsql" Version="8.0.3" PrivateAssets="All"/>
<PackageReference Include="Sandwych.GeographicLib" Version="1.49.3" />
<PackageReference Include="Stubble.Core" Version="1.8.4" />
<PackageReference Include="System.DirectoryServices" Version="4.7.0" />
Expand Down
3 changes: 3 additions & 0 deletions dotnet/src/dotnetcore/GxClasses/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@
[assembly: InternalsVisibleTo("DotNetCoreChunkedTest")]
[assembly: InternalsVisibleTo("DotNetCoreChunkedTest")]
[assembly: InternalsVisibleTo("GeneXus.OpenTelemetry.Diagnostics")]
[assembly: InternalsVisibleTo("ConsoleApp2")]
[assembly: InternalsVisibleTo("GxAI")]

15 changes: 15 additions & 0 deletions dotnet/src/dotnetcore/Providers/AI/GxAI.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net8.0</TargetFrameworks>
<PackageTags>Genexus AI</PackageTags>
<PackageId>GeneXus.AI.Core</PackageId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OpenAI" Version="2.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\GxClasses\GxClasses.csproj" />
</ItemGroup>


</Project>
82 changes: 82 additions & 0 deletions dotnet/src/dotnetcore/Providers/AI/Model/GXAgent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using GeneXus.AI.Chat;
using GeneXus.Procedure;
using GeneXus.Utils;

namespace GeneXus.AI
{
public class GXAgent : GXProcedure
{
static readonly IGXLogger log = GXLoggerFactory.GetLogger<GXAgent>();
const string FINISH_REASON_STOP = "stop";
const string FINISH_REASON_TOOL_CALLS = "tool_calls";
protected string CallAssistant(string assistant, GXProperties properties, object result)
{
return CallAgent(assistant, properties, null, result);
}
protected string CallAgent(string assistant, GXProperties gxproperties, IList chatMessages, object result)
{
CallResult callResult = result as CallResult;
try
{
GXLogging.Debug(log, "Calling Agent: ", assistant);

List<ChatMessage> chatMessagesList = chatMessages!=null ? chatMessages.Cast<ChatMessage>().ToList() :null;
ChatCompletionResult chatCompletion = AgentService.AgentHandlerInstance.Assistant(assistant, chatMessagesList, gxproperties).GetAwaiter().GetResult();

if (chatCompletion != null && chatCompletion.Choices != null)
{
foreach (Choice choice in chatCompletion.Choices)
{
switch (choice.FinishReason.ToLower())
{
case FINISH_REASON_STOP:
return choice.Message.Content;
case FINISH_REASON_TOOL_CALLS:
chatMessagesList.Add(choice.Message);
foreach (ToolCall toolCall in choice.Message.ToolCalls)
ProcessTollCall(toolCall, chatMessagesList);
return CallAgent(assistant, gxproperties, chatMessagesList, result);
}
}
}
return string.Empty;
}
catch (Exception ex)
{
callResult.AddMessage($"Error calling Agent {assistant}:" + ex.Message);
callResult.IsFail = true;
return string.Empty;
}

}
private void ProcessTollCall(ToolCall toolCall, List<ChatMessage> messages)
{
string result = string.Empty;
string functionName = toolCall.Function.Name;
try
{
result = CallTool(functionName, toolCall.Function.Arguments);
}
catch (Exception ex)
{
GXLogging.Error(log, "Error calling tool ", functionName, ex);
result = $"Error calling tool {functionName}";
}
ChatMessage toolCallMessage = new ChatMessage();
toolCallMessage.Role = "tool";
toolCallMessage.Content = result;
toolCallMessage.ToolCallId = toolCall.Id;
messages.Add(toolCallMessage);
}
protected virtual string CallTool(string name, string arguments)
{
return string.Empty;
}


}
}
4 changes: 4 additions & 0 deletions dotnet/src/dotnetcore/Providers/AI/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("DotNetCoreUnitTest")]
[assembly: InternalsVisibleTo("ConsoleApp2")]
Loading
Loading