Skip to content

Commit c588591

Browse files
Merge pull request #5 from wisedev-code/feat/move_to_llamaSharp_remove_ollama_dep
Feat/move to llama sharp remove ollama dep
2 parents c0666ce + 09bb378 commit c588591

57 files changed

Lines changed: 1036 additions & 287 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.models

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
gemma2:2b
2-
llama3.1:8b
3-
llama3.2:3b
4-
phi3.5
5-
llava
1+
62
#Place any new model here and it will be downloaded during start command
73

Flows/JobFinder/IT Job Finder.zip

-21 Bytes
Binary file not shown.

Flows/JobFinder/actor_1.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
"order": 1,
44
"name": "IT Job Finder",
55
"description": "1st in a flow",
6-
"model": "llama3.1:8b",
6+
"model": "gemma2:2b",
7+
"behaviours": { "Finder": "Extract best 5 jobs that you can find in memory. Try to include details such us company name, location, salary and job title. Present your response in nice and professional way" },
78
"context":
89
{
9-
"instruction": "Include complete job list from user input (always include all offers to show complete list), provide link to job if possible. Also mentione source of information if possible",
10-
"steps": ["REDIRECT+0248fe87-0b28-4590-9afb-77eeb45d8bc3+AS_Output", "REDIRECT+1315fb24-72c1-4a0c-98bd-0934496dda32+AS_Output", "REDIRECT+cd058053-ddba-4f37-b3f9-8759d6b9e0c7+AS_Output", "ANSWER"]
10+
"instruction": "Process information from redirect messages",
11+
"steps": ["REDIRECT+0248fe87-0b28-4590-9afb-77eeb45d8bc3+AS_Output+MEMORY", "REDIRECT+1315fb24-72c1-4a0c-98bd-0934496dda32+AS_Output+MEMORY", "REDIRECT+cd058053-ddba-4f37-b3f9-8759d6b9e0c7+AS_Output+MEMORY", "BECOME+Finder", "ANSWER+USE_MEMORY"]
1112
}
1213
}

Flows/JobFinder/actor_2.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
"name": "RemoteOK seeker",
55
"description": "2st in a flow",
66
"model": "llama3.2:3b",
7-
"behaviours": { "Seeker": "Write summary of jobs offers included in json (title, position, salary, company, provide job link if possible) ",
8-
"Extractor": "Extract at least 5 best jobs postings (and mentione source: in your remoteok.com) from all summaries you created that fits user filter: @filter@" },
7+
"behaviours": { "Extractor": "Extract at least 4 jobs offers (try to include title, company name, salary and location if possible). User filter is: @filter@" },
98
"context":
109
{
1110
"source":
@@ -17,11 +16,11 @@
1716
"method": "Get",
1817
"query": "",
1918
"payload": "",
20-
"chunkLimit": 15,
19+
"chunkLimit": 20,
2120
"responseType": "JSON"
2221
}
2322
},
24-
"instruction": "Here you can see list of tags that are available to you. You will get request from user request related to job search and you need to prepare filter in this format filter::{query}. If user is looking for backend python positon filter should look like this filter::{python,backend}. Plese focus on filter format it has to be correct. Its very important filter::{something}. Write filter only once in order to be properly replaced. Also be carefull with tags, you cannot use anything that its not present on the list. Here you can see list of tags: engineer, dev, backend, frontend, full stack, cloud, javascript, python, react, net, devops, sql, aws, docker, linux, java, golang, mobile, ios, android, graphql, typescript, node, html, css, testing, kubernetes, product manager, remote, designer, ui/ux, data science, machine learning",
25-
"steps": ["ANSWER", "BECOME+Seeker", "FETCH_DATA", "BECOME+Extractor", "ANSWER", "REDIRECT+f14cec0d-9acc-479f-bf39-b9a14d685af4+AS_Output+REPLACE"]
23+
"instruction": "Here you can see list of tags that are available to you. You will get request from user request related to job search and you need to prepare filter in this format filter::{query}. Dont include anything else in response, and there should be only one filter. If user is looking for backend python positon filter should look like this filter::{python,backend}. Plese focus on filter format it has to be correct. Its very important filter::{something}. Write filter only once in order to be properly replaced. Also be carefull with tags, you cannot use anything that its not present on the list. Here you can see list of tags: engineer, dev, backend, frontend, full stack, cloud, javascript, python, react, net, devops, sql, aws, docker, linux, java, golang, mobile, ios, android, graphql, typescript, node, html, css, testing, kubernetes, product manager, remote, designer, ui/ux, data science, machine learning",
24+
"steps": ["ANSWER","BECOME+Extractor", "FETCH_DATA", "REDIRECT+f14cec0d-9acc-479f-bf39-b9a14d685af4+AS_Output+REPLACE"]
2625
}
2726
}

Flows/JobFinder/actor_3.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
"name": "TheMuse seeker",
55
"description": "3st in a flow",
66
"model": "llama3.2:3b",
7-
"behaviours": { "Seeker": "Write summary of jobs offers included in json (title, position, salary, company, provide job link if possible)",
8-
"Extractor": "Extract at least 5 best jobs postings (and mentione source: in your case its themuse.com) from all summaries you created that fits user filter: @filter@" },
7+
"behaviours": { "Extractor": "Extract at least 4 jobs offers (try to include title, company name, salary and location if possible). User filter is: @filter@" },
98
"context":
109
{
1110
"source":
@@ -17,11 +16,11 @@
1716
"method": "Get",
1817
"query": "",
1918
"payload": "",
20-
"chunkLimit": 15,
19+
"chunkLimit": 20,
2120
"responseType": "JSON"
2221
}
2322
},
24-
"instruction": "Here you can see list of tags that are available to you. You will get request from user request related to job search and you need to prepare filter in this format filter::{query}. If user is looking for backend python positon filter should look like this filter::{python,backend} Here you can see list of tags: engineer, dev, backend, frontend, full stack, cloud, javascript, python, react, c#, devops, sql, aws, docker, linux, java, golang, mobile, ios, android, graphql, typescript, node, html, css, testing, kubernetes, product manager, remote, designer, ui/ux, data science, machine learning",
25-
"steps": ["ANSWER", "BECOME+Seeker", "FETCH_DATA", "BECOME+Extractor", "ANSWER", "REDIRECT+f14cec0d-9acc-479f-bf39-b9a14d685af4+AS_Output+REPLACE"]
23+
"instruction": "Here you can see list of tags that are available to you. You will get request from user request related to job search and you need to prepare filter in this format filter::{query}. Dont include anything else in response, and there should be only one filter. If user is looking for backend python positon filter should look like this filter::{python,backend} Here you can see list of tags: engineer, dev, backend, frontend, full stack, cloud, javascript, python, react, c#, devops, sql, aws, docker, linux, java, golang, mobile, ios, android, graphql, typescript, node, html, css, testing, kubernetes, product manager, remote, designer, ui/ux, data science, machine learning",
24+
"steps": ["ANSWER", "BECOME+Extractor", "FETCH_DATA", "REDIRECT+f14cec0d-9acc-479f-bf39-b9a14d685af4+AS_Output+REPLACE"]
2625
}
2726
}

Flows/JobFinder/actor_4.json

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44
"name": "4DaysWeek seeker",
55
"description": "4st in a flow",
66
"model": "llama3.2:3b",
7-
"behaviours": { "Seeker": "Write summary of jobs offers included in json (title, position, salary, company, provide job link if possible)",
8-
"Extractor": "Extract at least 5 best jobs postings (and mentione source: in your case its 4dayweek.io) from all summaries you created that fits user filter: @filter@" },
7+
"behaviours": { "Extractor": "Extract at least 4 jobs offers (try to include title, company name, salary and location if possible). User filter is: @filter@" },
98
"context":
109
{
1110
"source":
@@ -17,11 +16,11 @@
1716
"method": "Get",
1817
"query": "",
1918
"payload": "",
20-
"chunkLimit": 15,
19+
"chunkLimit": 20,
2120
"responseType": "JSON"
2221
}
2322
},
24-
"instruction": "Here you can see list of tags that are available to you. You will get request from user request related to job search and you need to prepare filter in this format filter::{query}. If user is looking for python positon filter should look like this filter::{Python}. Here is the list: engineer, dev, backend, frontend, full stack, cloud, javascript, python, react, net, devops, sql, aws, docker, linux, java, golang, mobile, ios, android, graphql, typescript, node, html, css, testing, kubernetes, product manager, remote, designer, ui/ux, data science, machine learning",
25-
"steps": ["ANSWER", "BECOME+Seeker", "FETCH_DATA", "BECOME+Extractor", "ANSWER", "REDIRECT+f14cec0d-9acc-479f-bf39-b9a14d685af4+AS_Output+REPLACE"]
23+
"instruction": "Here you can see list of tags that are available to you. You will get request from user request related to job search and you need to prepare filter in this format filter::{query}. Dont include anything else in response, and there should be only one filter. If user is looking for python positon filter should look like this filter::{Python}. Here is the list: engineer, dev, backend, frontend, full stack, cloud, javascript, python, react, net, devops, sql, aws, docker, linux, java, golang, mobile, ios, android, graphql, typescript, node, html, css, testing, kubernetes, product manager, remote, designer, ui/ux, data science, machine learning",
24+
"steps": ["ANSWER", "BECOME+Extractor", "FETCH_DATA", "REDIRECT+f14cec0d-9acc-479f-bf39-b9a14d685af4+AS_Output+REPLACE"]
2625
}
2726
}

Flows/JobFinder/actor_5.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"model": "llama3.2:3b",
77
"context":
88
{
9-
"instruction": "Prettify information about jobs and create clear list from given offers.",
9+
"instruction": "Prettify information about jobs and create clear list from given offers. Dont mentione that its prettified list, try to be professional with description",
1010
"steps": ["ANSWER"]
1111
}
1212
}

Frontend/MainFE/Components/Elements/ChatComponent.razor

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1+
@using System.Text
2+
@using System.Text.Json
13
@using MainFE.Components.Models
24
@using Markdig
5+
@using Microsoft.AspNetCore.SignalR.Client
36
@using Microsoft.FluentUI.AspNetCore.Components
7+
@using Microsoft.FluentUI.AspNetCore.Components.Icons.Filled
48
@using Message = MainFE.Components.Models.Message
59
@inject HttpClient Http
610
<link rel="stylesheet" href="css/chat.css">
@@ -12,8 +16,8 @@
1216
{
1317
continue;
1418
}
15-
16-
@if (message.Role != Role.System.ToString().ToLowerInvariant())
19+
20+
@if (message.Role != Role.System.ToString())
1721
{
1822
@if (Chat!.Visual)
1923
{
@@ -28,10 +32,12 @@
2832
{
2933
<FluentCard class="message-card-img bot-message" Style="height: 30rem !important; width: 30rem !important; ">
3034
<div>
31-
<a href="data:image/png;base64,@message.Images![0]"
32-
style="cursor: -webkit-zoom-in; cursor: zoom-in;" target="_blank"> <img src="data:image/png;base64,@message.Images![0]"
33-
style="object-fit: fill; width:100%; height:100%;"
34-
alt="imageResponse"/> </a>
35+
<a href="data:image/png;base64,@Convert.ToBase64String(message.Images!)"
36+
style="cursor: -webkit-zoom-in; cursor: zoom-in;" target="_blank">
37+
<img src="data:image/png;base64,@Convert.ToBase64String(message.Images!)"
38+
style="object-fit: fill; width:100%; height:100%;"
39+
alt="imageResponse"/>
40+
</a>
3541
</div>
3642
</FluentCard>
3743
}
@@ -52,20 +58,30 @@
5258
}
5359
@if (IsLoading)
5460
{
55-
<span class="message-role-bot">@_displayName</span>
5661
@if (Chat.Visual)
5762
{
63+
<span class="message-role-bot">@_displayName</span>
5864
<span class="message-role-bot" style="font-style: italic; font-size: small">This might take a while...</span>
5965
<FluentProgressRing Visible="IsLoading" Color="#afffab"></FluentProgressRing>
6066
}
6167
else
6268
{
63-
<FluentProgressRing Visible="IsLoading"></FluentProgressRing>
69+
<FluentStack>
70+
<span Class="message-role-bot">@_displayName</span>
71+
<FluentProgressRing Width="20px" Visible="IsLoading"></FluentProgressRing>
72+
</FluentStack>
73+
@if (_incomingMessage != null)
74+
{
75+
<FluentCard class="message-card bot-message">
76+
@((MarkupString)Markdown.ToHtml(_incomingMessage.ToString()!,
77+
new MarkdownPipelineBuilder()
78+
.UseAdvancedExtensions()
79+
.Build()))
80+
</FluentCard>
81+
}
6482
}
65-
66-
6783
}
68-
</div>
84+
</div >
6985
<div class="input-container">
7086
<FluentInputFile Id="my-file-uploader"
7187
Mode="InputFileMode.SaveToTemporaryFolder"
@@ -75,25 +91,23 @@
7591
Accept=".csv, .json, .txt"
7692
ProgressPercent="@ProgressPercent"
7793
OnCompleted="@OnFileCompletedAsync"
78-
Style="background-color: transparent !important; width: 3rem">
79-
<ChildContent>
94+
Style="background-color: transparent !important; width: 3rem; border-style: none !important;">
95+
<ChildContent >
8096
<label for="my-file-uploader" class="attachment-btn ">
81-
<FluentIcon Value="@(new Icons.Filled.Size32.Attach())"
82-
Color="@_filesAttachedClass" Style="margin-right: 5px; background-color: transparent">
83-
</FluentIcon>
84-
</label>
85-
</ChildContent>
86-
</FluentInputFile>
87-
97+
<FluentIcon Value="@(new Size32.Attach())"
98+
Color="@_filesAttachedClass" Style="margin-right: 5px; background-color: transparent">
99+
</FluentIcon >
100+
</label >
101+
</ChildContent >
102+
</FluentInputFile >
88103
<input @bind-value="_ask" @bind-value:event="oninput" placeholder="Enter your prompt here..." @onkeydown="CheckEnterKey" class="inp">
89-
90-
<FluentButton IconStart="@(new Icons.Filled.Size28.Send())" BackgroundColor="rgba(0, 0, 0, 0)" Style="margin-top: 5px; background-color: transparent"
104+
<FluentButton IconStart="@(new Size28.Send())" BackgroundColor="rgba(0, 0, 0, 0)" Style="margin-top: 5px; background-color: transparent"
91105
Appearance="Appearance.Lightweight"
92106
Loading="@IsLoading"
93107
OnClick="@(() => SendAsync(_ask))">
94-
</FluentButton>
95-
</div>
96-
<FluentProgress Visible="@(IsLoading)" style="width: 100%;"></FluentProgress>
108+
</FluentButton >
109+
</div >
110+
<FluentProgress Visible="@(IsLoading)" style="width: 100%;"></FluentProgress >
97111

98112
@code
99113
{
@@ -105,13 +119,43 @@
105119
[Parameter] public string? AgentId { get; set; }
106120
[Parameter] public FluentInputFileEventArgs[] Images { get; set; }
107121
[Parameter] public bool Translate { get; set; }
122+
[Parameter] public bool Stream { get; set; } = true;
108123

109124
public FluentInputFileEventArgs[] Files = [];
110125
private bool _filesAttached = false;
111126
private Color _filesAttachedClass => _filesAttached ? Color.Success : Color.Accent;
112127
private string _ask = string.Empty;
113128
private string _displayName => CustomName ?? SelectedModel;
129+
private StringBuilder? _incomingMessage = null;
114130
int ProgressPercent = 0;
131+
private HubConnection hubConnection;
132+
133+
protected override async Task OnInitializedAsync()
134+
{
135+
hubConnection = new HubConnectionBuilder()
136+
.WithUrl($"{ExtensionMethods.GetApiUrl()}/diagnostics")
137+
.Build();
138+
139+
hubConnection.On<JsonElement>("ReceiveMessageUpdate", (jsonElement) =>
140+
{
141+
_incomingMessage ??= new StringBuilder();
142+
var chatId = jsonElement.GetProperty("chatId").GetString();
143+
if (Chat?.Id != chatId) return;
144+
145+
var content = jsonElement.GetProperty("content").GetString();
146+
var done = jsonElement.GetProperty("done").GetBoolean();
147+
_incomingMessage = _incomingMessage.Append(content);
148+
149+
if (done)
150+
{
151+
_incomingMessage = null;
152+
}
153+
154+
InvokeAsync(StateHasChanged);
155+
});
156+
157+
await hubConnection.StartAsync();
158+
}
115159

116160
private async Task SendAsync(string message)
117161
{
@@ -129,11 +173,11 @@
129173
if (ExtensionMethods.IsVisionModel(SelectedModel) && Images.Any())
130174
{
131175
var file = await File.ReadAllBytesAsync(Images.First().LocalFile!.FullName);
132-
newMsg.Images = [Convert.ToBase64String(file)];
176+
newMsg.Images = file;
133177
Images = []; // Clear files
134178
}
135179

136-
if(Files.Any())
180+
if (Files.Any())
137181
{
138182
newMsg.Files = Files.Select(x => new FileData()
139183
{
@@ -143,9 +187,10 @@
143187
}).ToArray();
144188
_filesAttached = false;
145189
}
190+
146191
Chat.Model = SelectedModel;
147192

148-
var apiResponse = await Http.PostAsJsonAsync($"{ExtensionMethods.GetApiUrl()}/api/chats/complete?translate={Translate}", Chat);
193+
var apiResponse = await Http.PostAsJsonAsync($"{ExtensionMethods.GetApiUrl()}/api/chats/complete?translate={Translate}&interactiveUpdates={Stream}", Chat);
149194

150195
if (apiResponse.IsSuccessStatusCode)
151196
{
@@ -191,7 +236,7 @@
191236
SelectedModel = response.Model!;
192237
}
193238
}
194-
239+
195240
private async Task OnFileCompletedAsync(IEnumerable<FluentInputFileEventArgs> files)
196241
{
197242
Files = files.ToArray();
@@ -207,5 +252,4 @@
207252
}
208253

209254
private string GetRoleLabel(string role) => role == Role.User.ToString() ? "( ͡° ͜ʖ ͡°) User" : $"{_displayName}";
210-
}
211-
255+
}

Frontend/MainFE/Components/Models/ActorOutput.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ public class ActorOutput
66
public string UserMsg { get; set; }
77
public string ActorMsg { get; set; }
88

9-
public string? Image { get; set; }
9+
public byte[]? Image { get; set; }
1010
public bool IsExpanded { get; set; } = true;
1111
public DateTime Time { get; set; }
1212
public string Model { get; set; }

Frontend/MainFE/Components/Models/AgentDto.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,16 @@ public class AgentDto
2424
[JsonPropertyName("context")]
2525
public AgentContextDto Context { get; set; }
2626
public AgentProcessingState State { get; set; }
27-
2827
public bool IsProcessing { get; set; }
2928
public List<string>? AgentDependencies { get; set; } = [];
30-
public string? ProgressMessage { get; set; }
3129
public string? Behaviour { get; set; } = "Default";
30+
31+
public string ProgressMessage
32+
{
33+
get => string.IsNullOrEmpty(_progressMessage)
34+
? (IsProcessing ? "Thinking" : "Waiting")
35+
: _progressMessage;
36+
set => _progressMessage = value;
37+
}
38+
private string? _progressMessage;
3239
}

0 commit comments

Comments
 (0)