Skip to content

Commit 53ac6a9

Browse files
AlessiaYChenFosol
authored andcommitted
MMI-3258-update (bcgov#2549)
* update prompt * update
1 parent d05eb10 commit 53ac6a9

File tree

5 files changed

+101
-8
lines changed

5 files changed

+101
-8
lines changed

services/net/auto-clipper/Config/Stations/CKNW.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ text:
1818
"(?i)up next": Promo
1919
"(?i)coming up": Promo
2020
llm_segmentation: true
21-
llm_model: gpt-5.1-chat
22-
llm_temperature: 1 # Set to 0.0 for deterministic JSON and stable indices.
21+
llm_model: gpt-5-chat
22+
llm_temperature: 0.0 # Set to 0.0 for deterministic JSON and stable indices.
2323
system_prompt: |
2424
You are a Broadcast Structure Parser. Your ONLY job is to detect segment transitions.
2525
Output MUST be a single, raw JSON object.

services/net/auto-clipper/LLM/ClipSegmentationService.cs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -299,10 +299,10 @@ private IReadOnlyList<ClipDefinition> ParseResponse(string? body, IReadOnlyList<
299299
if (boundaries == null || boundaries.Boundaries == null) continue;
300300
foreach (var boundary in boundaries.Boundaries)
301301
{
302-
var rawIndex = boundary.Index;
303-
if (rawIndex <= 0)
302+
var normalizedIndex = NormalizeBoundaryIndex(boundary.Index);
303+
if (normalizedIndex <= 0)
304304
continue;
305-
var zeroIndex = Math.Clamp(rawIndex - 1, 0, transcript.Count - 1);
305+
var zeroIndex = Math.Clamp(normalizedIndex - 1, 0, transcript.Count - 1);
306306
var title = string.IsNullOrWhiteSpace(boundary.Title) ? "Clip" : boundary.Title;
307307
var summary = string.IsNullOrWhiteSpace(boundary.Summary) ? string.Empty : boundary.Summary;
308308
var category = string.IsNullOrWhiteSpace(boundary.Category) ? null : boundary.Category;
@@ -321,6 +321,14 @@ private IReadOnlyList<ClipDefinition> ParseResponse(string? body, IReadOnlyList<
321321
}
322322
}
323323

324+
private static int NormalizeBoundaryIndex(double value)
325+
{
326+
if (double.IsNaN(value) || double.IsInfinity(value)) return 0;
327+
if (value <= 0) return 0;
328+
var ceiled = (int)Math.Ceiling(value);
329+
return Math.Max(1, ceiled);
330+
}
331+
324332
private IReadOnlyList<ClipDefinition> CreateClipDefinitions(IReadOnlyList<TimestampedTranscript> transcript, List<BoundaryCandidate> candidates, double threshold, IReadOnlyList<HeuristicHit> heuristicHits)
325333
{
326334
if (transcript == null || transcript.Count == 0)
@@ -467,5 +475,3 @@ private static IReadOnlyList<ClipDefinition> FilterOverlaps(IReadOnlyList<ClipDe
467475

468476

469477

470-
471-

services/net/auto-clipper/LLM/Models/LLMMessage.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ public class LLMMessage
88
public string? Role { get; set; }
99

1010
[JsonPropertyName("content")]
11+
[JsonConverter(typeof(LlmMessageContentConverter))]
1112
public string? Content { get; set; }
1213
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Text;
4+
using System.Text.Json;
5+
using System.Text.Json.Serialization;
6+
7+
namespace TNO.Services.AutoClipper.LLM.Models;
8+
9+
/// <summary>
10+
/// Converts chat message content into a single string regardless of whether the payload is
11+
/// a plain string or the newer array-of-parts format returned by Azure OpenAI.
12+
/// </summary>
13+
internal sealed class LlmMessageContentConverter : JsonConverter<string?>
14+
{
15+
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
16+
{
17+
return reader.TokenType switch
18+
{
19+
JsonTokenType.String => reader.GetString(),
20+
JsonTokenType.Null => null,
21+
JsonTokenType.StartArray => ReadArray(ref reader),
22+
JsonTokenType.StartObject => ReadObject(ref reader),
23+
_ => ReadFallback(ref reader)
24+
};
25+
}
26+
27+
public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options)
28+
{
29+
writer.WriteStringValue(value);
30+
}
31+
32+
private static string? ReadArray(ref Utf8JsonReader reader)
33+
{
34+
using var doc = JsonDocument.ParseValue(ref reader);
35+
var builder = new StringBuilder();
36+
foreach (var element in doc.RootElement.EnumerateArray())
37+
{
38+
var text = ExtractText(element);
39+
if (string.IsNullOrWhiteSpace(text)) continue;
40+
if (builder.Length > 0) builder.AppendLine();
41+
builder.Append(text.Trim());
42+
}
43+
return builder.Length == 0 ? null : builder.ToString();
44+
}
45+
46+
private static string? ReadObject(ref Utf8JsonReader reader)
47+
{
48+
using var doc = JsonDocument.ParseValue(ref reader);
49+
return ExtractText(doc.RootElement);
50+
}
51+
52+
private static string? ReadFallback(ref Utf8JsonReader reader)
53+
{
54+
using var doc = JsonDocument.ParseValue(ref reader);
55+
return doc.RootElement.GetRawText();
56+
}
57+
58+
private static string? ExtractText(JsonElement element)
59+
{
60+
return element.ValueKind switch
61+
{
62+
JsonValueKind.String => element.GetString(),
63+
JsonValueKind.Object when element.TryGetProperty("text", out var textNode) && textNode.ValueKind == JsonValueKind.String
64+
=> textNode.GetString(),
65+
JsonValueKind.Object when element.TryGetProperty("content", out var nested) && nested.ValueKind == JsonValueKind.String
66+
=> nested.GetString(),
67+
JsonValueKind.Object when element.TryGetProperty("type", out var typeNode)
68+
=> ExtractTextFromTypedNode(element, typeNode),
69+
JsonValueKind.Number => element.GetDouble().ToString(CultureInfo.InvariantCulture),
70+
JsonValueKind.True => "true",
71+
JsonValueKind.False => "false",
72+
_ => element.GetRawText()
73+
};
74+
}
75+
76+
private static string? ExtractTextFromTypedNode(JsonElement element, JsonElement typeNode)
77+
{
78+
var type = typeNode.ValueKind == JsonValueKind.String ? typeNode.GetString() : null;
79+
if (string.Equals(type, "text", StringComparison.OrdinalIgnoreCase) && element.TryGetProperty("text", out var text) && text.ValueKind == JsonValueKind.String)
80+
return text.GetString();
81+
if (string.Equals(type, "tool_result", StringComparison.OrdinalIgnoreCase) && element.TryGetProperty("content", out var nested))
82+
return nested.ValueKind == JsonValueKind.String ? nested.GetString() : nested.GetRawText();
83+
return element.GetRawText();
84+
}
85+
}

services/net/auto-clipper/LLM/Models/TranscriptBoundary.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ namespace TNO.Services.AutoClipper.LLM.Models;
55
public class TranscriptBoundary
66
{
77
[JsonPropertyName("index")]
8-
public int Index { get; set; }
8+
[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
9+
public double Index { get; set; }
910

1011
[JsonPropertyName("title")]
1112
public string Title { get; set; } = "";

0 commit comments

Comments
 (0)