1
1
using System ;
2
2
using System . Collections . Generic ;
3
+ using System . Linq ;
3
4
using GarageGroup . Infra . Bot . Builder ;
4
5
5
6
namespace GarageGroup . Internal . Support ;
@@ -19,11 +20,86 @@ internal static void TraceGpt(this IncidentCreateFlowOption option, IChatFlowCon
19
20
[ "flowId" ] = context . ChatFlowId ,
20
21
[ "event" ] = "GptUsage" ,
21
22
[ "isGptUsed" ] = isGptUsed ? "true" : "false" ,
23
+ [ "similarityGptByCharacters" ] = CalculateSimilarityByCharacters ( context . FlowState . Gpt . Title , context . FlowState . Title . OrEmpty ( ) ) . ToString ( ) ,
24
+ [ "similarityGptByWords" ] = CalculateSimilarityByWords ( context . FlowState . Gpt . Title , context . FlowState . Title . OrEmpty ( ) ) . ToString ( ) ,
22
25
[ "gptTitle" ] = context . FlowState . Gpt . Title ,
23
26
[ "selectedTitle" ] = context . FlowState . Title . OrEmpty ( ) ,
24
27
[ "sourceDescription" ] = context . FlowState . Gpt . SourceMessage . OrEmpty ( ) ,
25
28
} ;
26
29
27
30
context . BotTelemetryClient . TrackEvent ( "CompleteIncidentGptUsage" , properties ) ;
28
31
}
32
+
33
+ private static double CalculateSimilarityByCharacters ( string generatedTitle , string finalTitle )
34
+ {
35
+ var editDistance = new int [ generatedTitle . Length + 1 , finalTitle . Length + 1 ] ;
36
+
37
+ for ( var i = 0 ; i <= generatedTitle . Length ; i ++ )
38
+ {
39
+ for ( var j = 0 ; j <= finalTitle . Length ; j ++ )
40
+ {
41
+ if ( i == 0 )
42
+ {
43
+ editDistance [ i , j ] = j ;
44
+ }
45
+ else if ( j == 0 )
46
+ {
47
+ editDistance [ i , j ] = i ;
48
+ }
49
+ else
50
+ {
51
+ editDistance [ i , j ] = Math . Min (
52
+ Math . Min ( editDistance [ i - 1 , j ] + 1 , editDistance [ i , j - 1 ] + 1 ) ,
53
+ editDistance [ i - 1 , j - 1 ] + ( generatedTitle [ i - 1 ] == finalTitle [ j - 1 ] ? 0 : 1 ) ) ;
54
+ }
55
+ }
56
+ }
57
+
58
+ var maxLength = Math . Max ( generatedTitle . Length , finalTitle . Length ) ;
59
+ var similarity = 1.0 - ( double ) editDistance [ generatedTitle . Length , finalTitle . Length ] / maxLength ;
60
+
61
+ return Math . Round ( similarity , 3 ) ;
62
+ }
63
+
64
+ private static double CalculateSimilarityByWords ( string generatedTitle , string finalTitle )
65
+ {
66
+ var wordFreqGenerated = GetWordFrequency ( generatedTitle ) ;
67
+ var wordFreqFinal = GetWordFrequency ( finalTitle ) ;
68
+
69
+ var allWords = new HashSet < string > ( ) ;
70
+ allWords . UnionWith ( wordFreqGenerated . Keys ) ;
71
+ allWords . UnionWith ( wordFreqFinal . Keys ) ;
72
+
73
+ var vectorGenerated = new List < int > ( ) ;
74
+ var vectorFinal = new List < int > ( ) ;
75
+
76
+ foreach ( var word in allWords )
77
+ {
78
+ vectorGenerated . Add ( wordFreqGenerated . ContainsKey ( word ) ? wordFreqGenerated [ word ] : 0 ) ;
79
+ vectorFinal . Add ( wordFreqFinal . ContainsKey ( word ) ? wordFreqFinal [ word ] : 0 ) ;
80
+ }
81
+
82
+ var dotProduct = CalculateDotProduct ( vectorGenerated , vectorFinal ) ;
83
+ var magnitudeGenerated = Math . Sqrt ( CalculateDotProduct ( vectorGenerated , vectorGenerated ) ) ;
84
+ var magnitudeFinal = Math . Sqrt ( CalculateDotProduct ( vectorFinal , vectorFinal ) ) ;
85
+
86
+ var similarity = dotProduct / ( magnitudeGenerated * magnitudeFinal ) ;
87
+ return Math . Round ( similarity , 3 ) ;
88
+
89
+ static Dictionary < string , int > GetWordFrequency ( string title )
90
+ =>
91
+ title . Split ( new [ ] { ' ' , ',' , '.' , '!' , '?' } , StringSplitOptions . RemoveEmptyEntries )
92
+ . GroupBy ( word => word . ToLower ( ) )
93
+ . ToDictionary ( group => group . Key , group => group . Count ( ) ) ;
94
+
95
+ static double CalculateDotProduct ( List < int > firstVector , List < int > secondVector )
96
+ {
97
+ var result = 0 ;
98
+ for ( int i = 0 ; i < firstVector . Count ; i ++ )
99
+ {
100
+ result += firstVector [ i ] * secondVector [ i ] ;
101
+ }
102
+ return result ;
103
+ }
104
+ }
29
105
}
0 commit comments