Fix HF dataset import internal error and training SQLite readiness.
Wrap AssistentImportHfDataset in try/catch, batch inserts in a transaction, clearer HF rows errors for gated datasets, EnsureTrainingReady with actionable message, and friendlier training UI errors instead of generic internal error. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+75
-45
@@ -68,7 +68,7 @@ public sealed partial class AssistentMemory
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureOpen();
|
||||
EnsureTrainingReady();
|
||||
int take = Math.Clamp(limit, 1, 2000);
|
||||
List<string> where = [];
|
||||
if (!string.IsNullOrWhiteSpace(status) && !string.Equals(status, "all", StringComparison.OrdinalIgnoreCase))
|
||||
@@ -167,57 +167,87 @@ public sealed partial class AssistentMemory
|
||||
}
|
||||
}
|
||||
|
||||
public int ImportTrainSamplesBatch(IEnumerable<JObject> samples)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureTrainingReady();
|
||||
int imported = 0;
|
||||
using SqliteTransaction tx = _conn.BeginTransaction();
|
||||
foreach (JObject sample in samples)
|
||||
{
|
||||
if (sample is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
UpsertTrainSampleCore(sample, tx);
|
||||
imported++;
|
||||
}
|
||||
tx.Commit();
|
||||
return imported;
|
||||
}
|
||||
}
|
||||
|
||||
public JObject UpsertTrainSample(JObject sample)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureOpen();
|
||||
long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
string id = sample["id"]?.ToString()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
id = $"ts_{now}_{Guid.NewGuid():N}"[..24];
|
||||
}
|
||||
string datasetId = sample["dataset_id"]?.ToString()?.Trim() ?? "default";
|
||||
JArray messages = sample["messages"] as JArray ?? [];
|
||||
using SqliteCommand cmd = _conn.CreateCommand();
|
||||
cmd.CommandText =
|
||||
"""
|
||||
INSERT INTO train_samples(id, dataset_id, source, chat_id, persona, pack, hf_repo, messages_json, status, created_at, updated_at)
|
||||
VALUES($id, $ds, $src, $chat, $persona, $pack, $hf, $msg, $status, $c, $u)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
dataset_id = excluded.dataset_id,
|
||||
source = excluded.source,
|
||||
chat_id = excluded.chat_id,
|
||||
persona = excluded.persona,
|
||||
pack = excluded.pack,
|
||||
hf_repo = excluded.hf_repo,
|
||||
messages_json = excluded.messages_json,
|
||||
status = excluded.status,
|
||||
updated_at = excluded.updated_at
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("$id", id);
|
||||
cmd.Parameters.AddWithValue("$ds", datasetId);
|
||||
cmd.Parameters.AddWithValue("$src", sample["source"]?.ToString() ?? "manual");
|
||||
cmd.Parameters.AddWithValue("$chat", (object)sample["chat_id"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$persona", (object)sample["persona"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$pack", (object)sample["pack"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$hf", (object)sample["hf_repo"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$msg", messages.ToString(Newtonsoft.Json.Formatting.None));
|
||||
cmd.Parameters.AddWithValue("$status", sample["status"]?.ToString() ?? "draft");
|
||||
long created = sample["createdAt"]?.Value<long?>() ?? now;
|
||||
cmd.Parameters.AddWithValue("$c", created);
|
||||
cmd.Parameters.AddWithValue("$u", now);
|
||||
cmd.ExecuteNonQuery();
|
||||
return new JObject { ["id"] = id, ["updatedAt"] = now };
|
||||
EnsureTrainingReady();
|
||||
return UpsertTrainSampleCore(sample, null);
|
||||
}
|
||||
}
|
||||
|
||||
JObject UpsertTrainSampleCore(JObject sample, SqliteTransaction tx)
|
||||
{
|
||||
long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
string id = sample["id"]?.ToString()?.Trim();
|
||||
if (string.IsNullOrWhiteSpace(id))
|
||||
{
|
||||
id = $"ts_{now}_{Guid.NewGuid():N}"[..24];
|
||||
}
|
||||
string datasetId = sample["dataset_id"]?.ToString()?.Trim() ?? "default";
|
||||
JArray messages = sample["messages"] as JArray ?? [];
|
||||
using SqliteCommand cmd = _conn.CreateCommand();
|
||||
if (tx is not null)
|
||||
{
|
||||
cmd.Transaction = tx;
|
||||
}
|
||||
cmd.CommandText =
|
||||
"""
|
||||
INSERT INTO train_samples(id, dataset_id, source, chat_id, persona, pack, hf_repo, messages_json, status, created_at, updated_at)
|
||||
VALUES($id, $ds, $src, $chat, $persona, $pack, $hf, $msg, $status, $c, $u)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
dataset_id = excluded.dataset_id,
|
||||
source = excluded.source,
|
||||
chat_id = excluded.chat_id,
|
||||
persona = excluded.persona,
|
||||
pack = excluded.pack,
|
||||
hf_repo = excluded.hf_repo,
|
||||
messages_json = excluded.messages_json,
|
||||
status = excluded.status,
|
||||
updated_at = excluded.updated_at
|
||||
""";
|
||||
cmd.Parameters.AddWithValue("$id", id);
|
||||
cmd.Parameters.AddWithValue("$ds", datasetId);
|
||||
cmd.Parameters.AddWithValue("$src", sample["source"]?.ToString() ?? "manual");
|
||||
cmd.Parameters.AddWithValue("$chat", (object)sample["chat_id"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$persona", (object)sample["persona"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$pack", (object)sample["pack"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$hf", (object)sample["hf_repo"]?.ToString() ?? DBNull.Value);
|
||||
cmd.Parameters.AddWithValue("$msg", messages.ToString(Newtonsoft.Json.Formatting.None));
|
||||
cmd.Parameters.AddWithValue("$status", sample["status"]?.ToString() ?? "draft");
|
||||
long created = sample["createdAt"]?.Value<long?>() ?? now;
|
||||
cmd.Parameters.AddWithValue("$c", created);
|
||||
cmd.Parameters.AddWithValue("$u", now);
|
||||
cmd.ExecuteNonQuery();
|
||||
return new JObject { ["id"] = id, ["updatedAt"] = now };
|
||||
}
|
||||
|
||||
public bool DeleteTrainSample(string id)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureOpen();
|
||||
EnsureTrainingReady();
|
||||
using SqliteCommand cmd = _conn.CreateCommand();
|
||||
cmd.CommandText = "DELETE FROM train_samples WHERE id = $id";
|
||||
cmd.Parameters.AddWithValue("$id", id ?? "");
|
||||
@@ -229,7 +259,7 @@ public sealed partial class AssistentMemory
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureOpen();
|
||||
EnsureTrainingReady();
|
||||
using SqliteCommand cmd = _conn.CreateCommand();
|
||||
if (string.IsNullOrWhiteSpace(status) || string.Equals(status, "all", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
@@ -288,7 +318,7 @@ public sealed partial class AssistentMemory
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureOpen();
|
||||
EnsureTrainingReady();
|
||||
using SqliteCommand cmd = _conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT id, kind, status, config_json, base_model, output_name, log_path, progress_json, created_at, updated_at, finished_at FROM train_jobs WHERE id = $id";
|
||||
cmd.Parameters.AddWithValue("$id", id ?? "");
|
||||
@@ -305,7 +335,7 @@ public sealed partial class AssistentMemory
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureOpen();
|
||||
EnsureTrainingReady();
|
||||
using SqliteCommand cmd = _conn.CreateCommand();
|
||||
cmd.CommandText =
|
||||
"SELECT id, kind, status, config_json, base_model, output_name, log_path, progress_json, created_at, updated_at, finished_at "
|
||||
@@ -341,7 +371,7 @@ public sealed partial class AssistentMemory
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
EnsureOpen();
|
||||
EnsureTrainingReady();
|
||||
using SqliteCommand cmd = _conn.CreateCommand();
|
||||
cmd.CommandText = "SELECT id, kind, status, config_json, base_model, output_name, log_path, progress_json, created_at, updated_at, finished_at FROM train_jobs WHERE status IN ('pending','running') ORDER BY updated_at DESC LIMIT 1";
|
||||
using SqliteDataReader r = cmd.ExecuteReader();
|
||||
|
||||
Reference in New Issue
Block a user