Skip to content

Commit d1602e9

Browse files
authored
Merge pull request #14 from wisedev-code/feat/use-files-stream
WithFiles - option for streams
2 parents 6cf4a3a + 3a7cb6c commit d1602e9

15 files changed

Lines changed: 199 additions & 13 deletions

File tree

.github/workflows/publish.yml

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,63 @@ jobs:
2929
- name: Run tests
3030
run: dotnet test --configuration Release --no-build --verbosity normal --filter FullyQualifiedName\!~IntegrationTests
3131

32+
- name: Get Version
33+
run: |
34+
NUSPEC_VERSION=$(grep -oP '(?<=<version>).*?(?=</version>)' MaIN.Core/*.nuspec | head -1)
35+
echo "NUSPEC_VERSION=${NUSPEC_VERSION}" >> $GITHUB_ENV
36+
echo "nuspec_version=${NUSPEC_VERSION}" >> $GITHUB_OUTPUT
37+
38+
- name: Get latest release version
39+
uses: octokit/request-action@v2.x
40+
with:
41+
route: GET /repos/{owner}/{repo}/releases/latest
42+
owner: ${{ github.repository_owner }}
43+
repo: ${{ github.event.repository.name }}
44+
env:
45+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
46+
continue-on-error: true
47+
48+
- name: Extract latest version
49+
id: extract-latest
50+
run: |
51+
if [ "${{ steps.latest-release.outcome }}" == "success" ]; then
52+
LATEST_VERSION=$(echo '${{ steps.latest-release.outputs.data }}' | jq -r '.tag_name' | sed 's/^v//')
53+
echo "LATEST_VERSION=${LATEST_VERSION}" >> $GITHUB_ENV
54+
echo "latest_version=${LATEST_VERSION}" >> $GITHUB_OUTPUT
55+
else
56+
echo "No previous release found"
57+
echo "LATEST_VERSION=0.0.0" >> $GITHUB_ENV
58+
echo "latest_version=0.0.0" >> $GITHUB_OUTPUT
59+
fi
60+
61+
- name: Compare versions
62+
id: compare-versions
63+
run: |
64+
echo "Nuspec version: ${{ env.NUSPEC_VERSION }}"
65+
echo "Latest release version: ${{ env.LATEST_VERSION }}"
66+
67+
if [ "${{ env.NUSPEC_VERSION }}" != "${{ env.LATEST_VERSION }}" ]; then
68+
echo "Versions are different - creating a new release"
69+
echo "CREATE_RELEASE=true" >> $GITHUB_ENV
70+
echo "create_release=true" >> $GITHUB_OUTPUT
71+
else
72+
echo "Versions are the same - skipping release"
73+
echo "CREATE_RELEASE=false" >> $GITHUB_ENV
74+
echo "create_release=false" >> $GITHUB_OUTPUT
75+
fi
76+
3277
- name: Pack NuGet package
78+
if: env.CREATE_RELEASE == 'true'
3379
run: dotnet pack --configuration Release --output ./artifacts
3480

3581
- name: Push package to NuGet
82+
if: env.CREATE_RELEASE == 'true'
3683
env:
3784
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
3885
run: dotnet nuget push "./artifacts/*.nupkg" --source "https://api.nuget.org/v3/index.json" --api-key "$NUGET_API_KEY" --skip-duplicate
3986

4087
- name: Create GitHub Release
41-
if: github.ref == 'refs/heads/main'
88+
if: github.ref == 'refs/heads/main' && env.CREATE_RELEASE == 'true'
4289
env:
4390
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4491
run: |

Examples/Examples/Chat/ChatWithFilesExample.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ public async Task Start()
1717
.CompleteAsync();
1818

1919
Console.WriteLine(result.Message.Content);
20+
Console.ReadKey();
2021
}
2122
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using MaIN.Core.Hub;
2+
3+
namespace Examples;
4+
5+
//TODO: this will be moved to test cases. It's same as normal files but I want to test streams
6+
public class ChatWithFilesFromStreamExample : IExample
7+
{
8+
public async Task Start()
9+
{
10+
Console.WriteLine("ChatExample with files is running!");
11+
12+
List<string> files = ["./Files/Nicolaus_Copernicus.pdf", "./Files/Galileo_Galilei.pdf"];
13+
14+
var fileStreams = new List<FileStream>();
15+
16+
foreach (var path in files)
17+
{
18+
if (File.Exists(path))
19+
{
20+
// Open file with read access
21+
FileStream fs = new FileStream(
22+
path,
23+
FileMode.Open,
24+
FileAccess.Read,
25+
FileShare.Read);
26+
27+
fileStreams.Add(fs);
28+
Console.WriteLine($"Loaded: {path}");
29+
}
30+
else
31+
{
32+
Console.WriteLine($"File not found: {path}");
33+
}
34+
}
35+
36+
var result = await AIHub.Chat()
37+
.WithModel("gemma2:2b")
38+
.WithMessage("You have 2 documents in memory. Whats the difference of work between Galileo and Copernicus?. Give answer based on the documents.")
39+
.WithFiles(fileStreams)
40+
.CompleteAsync();
41+
42+
Console.WriteLine(result.Message.Content);
43+
Console.ReadKey();
44+
}
45+
}

Examples/Examples/Program.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ static void RegisterExamples(IServiceCollection services)
4343
services.AddTransient<ExampleRegistry>();
4444
services.AddTransient<ChatExample>();
4545
services.AddTransient<ChatWithFilesExample>();
46+
services.AddTransient<ChatWithFilesFromStreamExample>();
4647
services.AddTransient<ChatWithVisionExample>();
4748
services.AddTransient<ChatWithImageGenExample>();
4849
services.AddTransient<ChatFromExistingExample>();
@@ -122,6 +123,7 @@ public class ExampleRegistry(IServiceProvider serviceProvider)
122123
{
123124
("\u25a0 Basic Chat", _serviceProvider.GetRequiredService<ChatExample>()),
124125
("\u25a0 Chat with Files", _serviceProvider.GetRequiredService<ChatWithFilesExample>()),
126+
("\u25a0 Chat with Files from stream", _serviceProvider.GetRequiredService<ChatWithFilesFromStreamExample>()),
125127
("\u25a0 Chat with Vision", _serviceProvider.GetRequiredService<ChatWithVisionExample>()),
126128
("\u25a0 Chat with Image Generation", _serviceProvider.GetRequiredService<ChatWithImageGenExample>()),
127129
("\u25a0 Chat from Existing", _serviceProvider.GetRequiredService<ChatFromExistingExample>()),

MaIN.Core.IntegrationTests/ChatTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,36 @@ public async Task Should_GenerateImage_BasedOnPrompt()
9595
Assert.True(result.Done);
9696
Assert.NotNull(result.Message.Images);
9797
}
98+
99+
[Fact]
100+
public async Task Should_AnswerDifferences_BetweenDocuments_ChatWithFiles_UsingStreams()
101+
{
102+
List<string> files = ["./Files/Nicolaus_Copernicus.pdf", "./Files/Galileo_Galilei.pdf"];
103+
104+
var fileStreams = new List<FileStream>();
105+
106+
foreach (var path in files)
107+
{
108+
if (!File.Exists(path))
109+
continue;
110+
111+
var fs = new FileStream(
112+
path,
113+
FileMode.Open,
114+
FileAccess.Read,
115+
FileShare.Read);
116+
117+
fileStreams.Add(fs);
118+
}
119+
120+
var result = await AIHub.Chat()
121+
.WithModel("gemma2:2b")
122+
.WithMessage("You have 2 documents in memory. Whats the difference of work between Galileo and Copernicus?. Give answer based on the documents.")
123+
.WithFiles(fileStreams)
124+
.CompleteAsync();
125+
126+
Assert.True(result.Done);
127+
Assert.NotNull(result.Message);
128+
Assert.NotEmpty(result.Message.Content);
129+
}
98130
}

MaIN.Server/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
app.MapPost("/api/llm/askmemory", async ([FromServices] ILLMService llmService, AskMemoryRequest request) =>
3636
{
37-
var result = await llmService.AskMemory(request.Chat, request.TextData, request.FileData, request.Memory);
37+
var result = await llmService.AskMemory(request.Chat, request.TextData, request.FileData, new Dictionary<string, FileStream>(), request.Memory);
3838
return result != null
3939
? Results.Ok(result)
4040
: Results.BadRequest("Failed to process the memory request.");

Releases/0.0.9-pre.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 0.0.9 pre-release
2+
3+
- New WithFiles() overload for uploading files via FileStreams

src/MaIN.Core/.nuspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<package>
33
<metadata>
44
<id>MaIN.NET</id>
5-
<version>0.0.8-pre</version>
5+
<version>0.0.9-pre</version>
66
<authors>Wisedev</authors>
77
<owners>Wisedev</owners>
88
<icon>favicon.png</icon>

src/MaIN.Core/Hub/Contexts/ChatContext.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,24 @@ public ChatContext WithSystemPrompt(string systemPrompt)
7474
return this;
7575
}
7676

77+
public ChatContext WithFiles(List<FileStream> fileStreams)
78+
{
79+
var files = fileStreams.Select(p => new FileInfo()
80+
{
81+
Name = Path.GetFileName(p.Name),
82+
Path = null,
83+
Extension = Path.GetExtension(p.Name),
84+
StreamContent = p
85+
}).ToList();
86+
87+
var lastMessage = _chat.Messages?.LastOrDefault();
88+
if (lastMessage != null)
89+
{
90+
lastMessage.Files = files;
91+
}
92+
return this;
93+
}
94+
7795
public ChatContext WithFiles(List<FileInfo> files)
7896
{
7997
var lastMessage = _chat.Messages?.LastOrDefault();

src/MaIN.Domain/Entities/FileInfo.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ public class FileInfo
55
public required string Name { get; set; }
66
public required string Extension { get; set; }
77
public string? Content { get; set; }
8+
public FileStream? StreamContent { get; set; }
89
public string? Path { get; set; }
910
}

0 commit comments

Comments
 (0)