chore: improve the result in classification closes #34

This commit is contained in:
Andre Henriques 2024-04-13 14:21:38 +01:00
parent 3f828ab855
commit f8bc8ad85a
7 changed files with 250 additions and 169 deletions

6
db.go
View File

@ -1,6 +0,0 @@
package main
import (
)

View File

@ -8,12 +8,32 @@ import (
)
func handleList(handler *Handle) {
handler.PostAuth("/tasks/task", 1, func(c *Context) *Error {
var getId JustId
if _err := c.ToJSON(&getId); _err != nil {
return _err
}
var task Task
err := GetDBOnce(c, &task, "tasks where id=$1;", getId.Id)
if err == NotFoundError {
return c.JsonBadRequest("Did not found task id")
} else if err != nil {
return c.E500M("Faied to get task", err)
}
c.ShowMessage = false
return c.SendJSON(task)
})
handler.PostAuth("/tasks/list", 1, func(c *Context) *Error {
var err error = nil
var err error = nil
var requestData struct {
ModelId string `json:"model_id"`
Page int `json:"page"`
Page int `json:"page"`
}
if _err := c.ToJSON(&requestData); _err != nil {
@ -33,15 +53,15 @@ func handleList(handler *Handle) {
}
}
var rows []*Task = nil
var rows []*Task = nil
if requestData.ModelId != "" {
rows, err = GetDbMultitple[Task](c, "tasks where model_id=$1 order by created_on desc limit 11 offset $2", requestData.ModelId, requestData.Page * 10)
rows, err = GetDbMultitple[Task](c, "tasks where model_id=$1 order by created_on desc limit 11 offset $2", requestData.ModelId, requestData.Page*10)
if err != nil {
return c.Error500(err)
}
} else {
rows, err = GetDbMultitple[Task](c, "tasks order by created_on desc limit 11 offset $1", requestData.Page * 10)
rows, err = GetDbMultitple[Task](c, "tasks order by created_on desc limit 11 offset $1", requestData.Page*10)
if err != nil {
return c.Error500(err)
}
@ -49,13 +69,13 @@ func handleList(handler *Handle) {
max_len := min(11, len(rows))
c.ShowMessage = false
c.ShowMessage = false
return c.SendJSON(struct {
TaskList []*Task `json:"task_list"`
ShowNext bool `json:"show_next"`
} {
rows[0:max_len],
len(rows) > 10,
})
TaskList []*Task `json:"task_list"`
ShowNext bool `json:"show_next"`
}{
rows[0:max_len],
len(rows) > 10,
})
})
}

12
main.go
View File

@ -8,10 +8,10 @@ import (
_ "github.com/lib/pq"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/models"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks"
models_utils "git.andr3h3nriqu3s.com/andr3/fyp/logic/models/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/tasks/runner"
. "git.andr3h3nriqu3s.com/andr3/fyp/logic/utils"
)
const (
@ -35,10 +35,10 @@ func main() {
defer db.Close()
log.Info("Starting server on :5002!")
config := LoadConfig()
log.Info("Config loaded!", "config", config)
config := LoadConfig()
log.Info("Config loaded!", "config", config)
StartRunners(db, config)
StartRunners(db, config)
//TODO check if file structure exists to save data
handle := NewHandler(db, config)
@ -59,7 +59,7 @@ func main() {
usersEndpints(db, handle)
HandleModels(handle)
HandleTasks(handle)
HandleTasks(handle)
handle.Startup()
}

View File

@ -0,0 +1,34 @@
<svg width="24" height="24" stroke="#000" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<style>
.spinner_V8m1 {
transform-origin: center;
animation: spinner_zKoa 2s linear infinite;
}
.spinner_V8m1 circle {
stroke-linecap: round;
animation: spinner_YpZS 1.5s ease-in-out infinite;
}
@keyframes spinner_zKoa {
100% {
transform: rotate(360deg);
}
}
@keyframes spinner_YpZS {
0% {
stroke-dasharray: 0 150;
stroke-dashoffset: 0;
}
47.5% {
stroke-dasharray: 42 150;
stroke-dashoffset: -16;
}
95%,
100% {
stroke-dasharray: 42 150;
stroke-dashoffset: -59;
}
}
</style><g class="spinner_V8m1"
><circle cx="12" cy="12" r="9.5" fill="none" stroke-width="3"></circle></g
>
</svg>

After

Width:  |  Height:  |  Size: 767 B

View File

@ -1,95 +1,111 @@
<script lang="ts">
import { postFormData } from "src/lib/requests.svelte";
import type { Model } from "./+page.svelte";
import FileUpload from "src/lib/FileUpload.svelte";
import MessageSimple from "src/lib/MessageSimple.svelte";
import { createEventDispatcher } from "svelte";
import { post, postFormData } from 'src/lib/requests.svelte';
import type { Model } from './+page.svelte';
import FileUpload from 'src/lib/FileUpload.svelte';
import MessageSimple from 'src/lib/MessageSimple.svelte';
import { createEventDispatcher, onDestroy } from 'svelte';
import Spinner from 'src/lib/Spinner.svelte';
import type { Task } from './TasksTable.svelte';
let {model} = $props<{model: Model}>();
let { model } = $props<{ model: Model }>();
let file: File | undefined = $state();
let file: File | undefined = $state();
const dispatch = createEventDispatcher<{ upload: void }>();
const dispatch = createEventDispatcher<{ upload: void; taskReload: void }>();
type Result = {
class: string,
confidence: number,
}
let _result: Promise<Task> = $state(new Promise(() => {}));
let run = $state(false);
let _result: Promise<Result | undefined> = $state(new Promise(() => {}));
let run = $state(false);
let last_task: string | undefined = $state();
let last_task: string | undefined = $state();
let last_task_timeout: number | null = null;
let messages: MessageSimple;
let messages: MessageSimple;
async function submit() {
if (!file) return;
messages.clear();
async function reloadLastTimeout() {
if (!last_task) {
return;
}
last_task_timeout = null;
let form = new FormData();
form.append("json_data", JSON.stringify({id: model.id}));
form.append("file", file, "file");
try {
const r = await post('tasks/task', { id: last_task });
if ([0, 1, 2, 3].includes(r.status)) {
setTimeout(reloadLastTimeout, 500);
setTimeout(() => dispatch('taskReload'), 500);
} else {
_result = Promise.resolve(r);
}
} catch (e) {
console.error('Failed to get data');
}
}
run = true;
async function submit() {
if (!file) return;
messages.clear();
try {
const r = await postFormData('tasks/start/image', form);
last_task = r.id
file = undefined;
} catch (e) {
if (e instanceof Response) {
messages.display(await e.json());
} else {
messages.display("Could not run the model");
}
}
let form = new FormData();
form.append('json_data', JSON.stringify({ id: model.id }));
form.append('file', file, 'file');
dispatch('upload');
}
run = true;
try {
const r = await postFormData('tasks/start/image', form);
last_task = r.id;
file = undefined;
last_task_timeout = setTimeout(() => reloadLastTimeout());
} catch (e) {
if (e instanceof Response) {
messages.display(await e.json());
} else {
messages.display('Could not run the model');
}
}
dispatch('upload');
}
onDestroy(() => {
if (last_task_timeout) {
clearTimeout(last_task_timeout);
}
});
</script>
<form on:submit|preventDefault={submit}>
<fieldset class="file-upload" >
<label for="file">Image</label>
<div class="form-msg">
Run image through them model and get the result
</div>
<FileUpload replace_slot bind:file accept="image/*" >
<img src="/imgs/upload-icon.png" alt="" />
<span>
Upload image
</span>
<div slot="replaced-name">
<span>
Image selected
</span>
</div>
</FileUpload>
</fieldset>
<MessageSimple bind:this={messages} />
<button>
Run
</button>
{#if run}
{#await _result}
<h1>
Processing Image {last_task}
</h1>
{:then result}
{#if !result}
<div class="result">
<h1>
The class was not found
</h1>
</div>
{:else}
<div>
<h1>
Result
</h1>
The image was classified as {result.class} with confidence: {result.confidence}
</div>
{/if}
{/await}
{/if}
</form>
<form on:submit|preventDefault={submit}>
<fieldset class="file-upload">
<label for="file">Image</label>
<div class="form-msg">Run image through them model and get the result</div>
<FileUpload replace_slot bind:file accept="image/*">
<img src="/imgs/upload-icon.png" alt="" />
<span> Upload image </span>
<div slot="replaced-name">
<span> Image selected </span>
</div>
</FileUpload>
</fieldset>
<MessageSimple bind:this={messages} />
<button> Run </button>
{#if run}
{#await _result}
<h1>
Processing Image! <Spinner />
</h1>
{:then result}
{#if result.status == 4}
{@const res = JSON.parse(result.result)}
<div>
<h1>Result</h1>
The image was classified as {res.class} with confidence: {res.confidence}
</div>
{:else}
<div class="result">
<h1>There was a problem running the task:</h1>
{result?.status_message}
</div>
{/if}
{/await}
{/if}
</form>

View File

@ -1,16 +1,15 @@
<script lang="ts">
import { post } from "src/lib/requests.svelte";
import type { Model } from "src/routes/models/edit/+page.svelte";
import RunModel from "./RunModel.svelte";
import TasksTable from "./TasksTable.svelte";
import { post } from 'src/lib/requests.svelte';
import type { Model } from 'src/routes/models/edit/+page.svelte';
import RunModel from './RunModel.svelte';
import TasksTable from './TasksTable.svelte';
const { active, model } = $props<{ active?: boolean, model: Model }>();
const { active, model } = $props<{ active?: boolean; model: Model }>();
let table: TasksTable;
let table: TasksTable;
</script>
<div class="content" class:selected={active}>
<RunModel model={model} on:upload={() => table.getList()} />
<TasksTable model={model} bind:this={table} />
<RunModel {model} on:upload={() => table.getList()} on:taskReload={() => table.getList()} />
<TasksTable {model} bind:this={table} />
</div>

View File

@ -8,8 +8,26 @@
user_confirmed: number;
compacted: number;
type: number;
created: string;
result: string;
created: string;
result: string;
};
export const TaskType = {
TASK_FAILED_RUNNING: -2,
TASK_FAILED_CREATION: -1,
TASK_PREPARING: 0,
TASK_TODO: 1,
TASK_PICKED_UP: 2,
TASK_RUNNING: 3,
TASK_DONE: 4
};
export const TaskTypeStrings: Record<number, string> = {
[-2]: 'Task failed running',
[-1]: 'Failed to create task',
0: 'Preparing task',
1: 'Task to do',
2: 'Task picked up by a runner',
3: 'Task running',
4: 'Task complete'
};
</script>
@ -17,34 +35,34 @@
import { post } from 'src/lib/requests.svelte';
import type { Model } from './+page.svelte';
let { model } = $props<{ model: Model, uploadCounter?: number }>();
let { model } = $props<{ model: Model; uploadCounter?: number }>();
let page = $state(0);
let showNext = $state(false);
let task_list = $state<Task[]>([]);
export async function getList() {
export async function getList() {
try {
const res = await post('tasks/list', {
id: model.id,
page: page,
});
const res = await post('tasks/list', {
id: model.id,
page: page
});
showNext = res.show_next;
task_list = res.task_list;
} catch (e) {
console.error('TODO notify user', e);
}
}
}
$effect(() => {
if (model) {
getList()
}
})
$effect(() => {
if (model) {
getList();
}
});
</script>
<div>
<h2>Tasks</h2>
<h2>Tasks</h2>
<table>
<thead>
<tr>
@ -63,11 +81,11 @@
{#each task_list as task}
<tr>
<td>
{#if task.type == 1}
Image Run
{:else}
{task.type}
{/if}
{#if task.type == 1}
Image Run
{:else}
{task.type}
{/if}
</td>
<td class="text-center">
{#if task.type == 1}
@ -83,42 +101,42 @@
{/if}
</td>
<td>
{#if task.type == 1}
{#if task.status == 4}
{#if task.user_confirmed == 0}
User has not agreed to the result of this task
{:else if task.user_confirmed == -1}
User has disagred with the result of this task
{:else if task.user_confirmed == 1}
User has aggred with the result of this task
{:else}
TODO {task.user_confirmed}
{/if}
{:else}
-
{/if}
{:else}
TODO Handle {task.type}
{/if}
{#if task.type == 1}
{#if task.status == 4}
{#if task.user_confirmed == 0}
User has not agreed to the result of this task
{:else if task.user_confirmed == -1}
User has disagred with the result of this task
{:else if task.user_confirmed == 1}
User has aggred with the result of this task
{:else}
TODO {task.user_confirmed}
{/if}
{:else}
-
{/if}
{:else}
TODO Handle {task.type}
{/if}
</td>
<td>
{#if task.status == 4}
{#if task.type == 1}
{@const temp = JSON.parse(task.result)}
{temp.class}({temp.confidence * 100}%)
{:else}
{task.result}
{/if}
{/if}
<td>
{#if task.status == 4}
{#if task.type == 1}
{@const temp = JSON.parse(task.result)}
{temp.class}({temp.confidence * 100}%)
{:else}
{task.result}
{/if}
{/if}
</td>
<td>
{task.status}
<td>
{TaskTypeStrings[task.status]}
</td>
<td>
{task.status_message}
<td>
{task.status_message}
</td>
<td>
{(new Date(task.created)).toLocaleString()}
<td>
{new Date(task.created).toLocaleString()}
</td>
</tr>
{/each}