@eucoder/rag 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +384 -0
  2. package/dist/ab-testing.d.ts +52 -0
  3. package/dist/ab-testing.d.ts.map +1 -0
  4. package/dist/ab-testing.js +144 -0
  5. package/dist/ab-testing.js.map +1 -0
  6. package/dist/ab-testing.test.d.ts +2 -0
  7. package/dist/ab-testing.test.d.ts.map +1 -0
  8. package/dist/ab-testing.test.js +147 -0
  9. package/dist/ab-testing.test.js.map +1 -0
  10. package/dist/agentic-rag.d.ts +23 -0
  11. package/dist/agentic-rag.d.ts.map +1 -0
  12. package/dist/agentic-rag.js +170 -0
  13. package/dist/agentic-rag.js.map +1 -0
  14. package/dist/agentic-rag.test.d.ts +2 -0
  15. package/dist/agentic-rag.test.d.ts.map +1 -0
  16. package/dist/agentic-rag.test.js +174 -0
  17. package/dist/agentic-rag.test.js.map +1 -0
  18. package/dist/corrective-rag.d.ts +16 -0
  19. package/dist/corrective-rag.d.ts.map +1 -0
  20. package/dist/corrective-rag.js +85 -0
  21. package/dist/corrective-rag.js.map +1 -0
  22. package/dist/corrective-rag.test.d.ts +2 -0
  23. package/dist/corrective-rag.test.d.ts.map +1 -0
  24. package/dist/corrective-rag.test.js +140 -0
  25. package/dist/corrective-rag.test.js.map +1 -0
  26. package/dist/feedback.d.ts +77 -0
  27. package/dist/feedback.d.ts.map +1 -0
  28. package/dist/feedback.js +44 -0
  29. package/dist/feedback.js.map +1 -0
  30. package/dist/feedback.test.d.ts +2 -0
  31. package/dist/feedback.test.d.ts.map +1 -0
  32. package/dist/feedback.test.js +202 -0
  33. package/dist/feedback.test.js.map +1 -0
  34. package/dist/hybrid-search.d.ts +14 -0
  35. package/dist/hybrid-search.d.ts.map +1 -0
  36. package/dist/hybrid-search.js +70 -0
  37. package/dist/hybrid-search.js.map +1 -0
  38. package/dist/hybrid-search.test.d.ts +2 -0
  39. package/dist/hybrid-search.test.d.ts.map +1 -0
  40. package/dist/hybrid-search.test.js +93 -0
  41. package/dist/hybrid-search.test.js.map +1 -0
  42. package/dist/index.d.ts +17 -0
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +12 -0
  45. package/dist/index.js.map +1 -0
  46. package/dist/knowledge-graph.d.ts +24 -0
  47. package/dist/knowledge-graph.d.ts.map +1 -0
  48. package/dist/knowledge-graph.js +131 -0
  49. package/dist/knowledge-graph.js.map +1 -0
  50. package/dist/knowledge-graph.test.d.ts +2 -0
  51. package/dist/knowledge-graph.test.d.ts.map +1 -0
  52. package/dist/knowledge-graph.test.js +140 -0
  53. package/dist/knowledge-graph.test.js.map +1 -0
  54. package/dist/llm-grader.d.ts +19 -0
  55. package/dist/llm-grader.d.ts.map +1 -0
  56. package/dist/llm-grader.js +63 -0
  57. package/dist/llm-grader.js.map +1 -0
  58. package/dist/metrics.d.ts +26 -0
  59. package/dist/metrics.d.ts.map +1 -0
  60. package/dist/metrics.js +100 -0
  61. package/dist/metrics.js.map +1 -0
  62. package/dist/optimizer.d.ts +52 -0
  63. package/dist/optimizer.d.ts.map +1 -0
  64. package/dist/optimizer.js +228 -0
  65. package/dist/optimizer.js.map +1 -0
  66. package/dist/optimizer.test.d.ts +2 -0
  67. package/dist/optimizer.test.d.ts.map +1 -0
  68. package/dist/optimizer.test.js +201 -0
  69. package/dist/optimizer.test.js.map +1 -0
  70. package/dist/self-improving.d.ts +85 -0
  71. package/dist/self-improving.d.ts.map +1 -0
  72. package/dist/self-improving.js +163 -0
  73. package/dist/self-improving.js.map +1 -0
  74. package/dist/self-improving.test.d.ts +2 -0
  75. package/dist/self-improving.test.d.ts.map +1 -0
  76. package/dist/self-improving.test.js +234 -0
  77. package/dist/self-improving.test.js.map +1 -0
  78. package/dist/types.d.ts +117 -0
  79. package/dist/types.d.ts.map +1 -0
  80. package/dist/types.js +2 -0
  81. package/dist/types.js.map +1 -0
  82. package/package.json +42 -0
  83. package/src/ab-testing.test.ts +239 -0
  84. package/src/ab-testing.ts +214 -0
  85. package/src/agentic-rag.test.ts +201 -0
  86. package/src/agentic-rag.ts +220 -0
  87. package/src/corrective-rag.test.ts +166 -0
  88. package/src/corrective-rag.ts +115 -0
  89. package/src/feedback.test.ts +227 -0
  90. package/src/feedback.ts +118 -0
  91. package/src/hybrid-search.test.ts +107 -0
  92. package/src/hybrid-search.ts +86 -0
  93. package/src/index.ts +57 -0
  94. package/src/knowledge-graph.test.ts +170 -0
  95. package/src/knowledge-graph.ts +182 -0
  96. package/src/llm-grader.ts +69 -0
  97. package/src/metrics.ts +121 -0
  98. package/src/optimizer.test.ts +232 -0
  99. package/src/optimizer.ts +307 -0
  100. package/src/self-improving.test.ts +341 -0
  101. package/src/self-improving.ts +239 -0
  102. package/src/types.ts +139 -0
  103. package/tsconfig.json +9 -0
@@ -0,0 +1,232 @@
1
+ import { describe, it, expect, beforeEach } from "vitest";
2
+ import { ParameterOptimizer } from "./optimizer.js";
3
+ import { InMemoryFeedbackStorage } from "./feedback.js";
4
+ import type { OptimizableParams } from "./optimizer.js";
5
+
6
+ describe("ParameterOptimizer", () => {
7
+ let optimizer: ParameterOptimizer;
8
+ let storage: InMemoryFeedbackStorage;
9
+
10
+ beforeEach(() => {
11
+ storage = new InMemoryFeedbackStorage();
12
+ optimizer = new ParameterOptimizer(storage);
13
+ });
14
+
15
+ it("should suggest collecting more data when feedback is insufficient", async () => {
16
+ const params: OptimizableParams = {
17
+ minScore: 0.5,
18
+ topK: 5,
19
+ };
20
+
21
+ // Add only 5 feedback (not enough)
22
+ for (let i = 0; i < 5; i++) {
23
+ await storage.saveFeedback({
24
+ id: `test-${i}`,
25
+ query: `query ${i}`,
26
+ answer: { text: `answer ${i}`, citations: [], steps: [], rewrites: 0 },
27
+ rating: 4,
28
+ relevance: 0.8,
29
+ completeness: 0.7,
30
+ citationsQuality: 0.9,
31
+ timestamp: new Date(),
32
+ strategy: "strategy-a",
33
+ });
34
+ }
35
+
36
+ const suggestions = await optimizer.analyzeAndSuggest("strategy-a", params);
37
+
38
+ expect(suggestions).toHaveLength(1);
39
+ expect(suggestions[0]?.type).toBe("strategy");
40
+ expect(suggestions[0]?.target).toBe("data_collection");
41
+ });
42
+
43
+ it("should suggest increasing minScore when relevance is low", async () => {
44
+ const params: OptimizableParams = {
45
+ minScore: 0.3,
46
+ topK: 10,
47
+ };
48
+
49
+ // Add 20 feedback with low relevance
50
+ for (let i = 0; i < 20; i++) {
51
+ await storage.saveFeedback({
52
+ id: `test-${i}`,
53
+ query: `query ${i}`,
54
+ answer: { text: `answer ${i}`, citations: [], steps: [], rewrites: 0 },
55
+ rating: 3,
56
+ relevance: 0.5,
57
+ completeness: 0.6,
58
+ citationsQuality: 0.7,
59
+ timestamp: new Date(),
60
+ strategy: "strategy-a",
61
+ });
62
+ }
63
+
64
+ const suggestions = await optimizer.analyzeAndSuggest("strategy-a", params);
65
+
66
+ const minScoreSuggestion = suggestions.find(s => s.target === "minScore");
67
+ expect(minScoreSuggestion).toBeDefined();
68
+ expect(minScoreSuggestion?.suggested).toBeGreaterThan(params.minScore!);
69
+ });
70
+
71
+ it("should suggest enabling self-reflection when completeness is low", async () => {
72
+ const params: OptimizableParams = {
73
+ enableSelfReflection: false,
74
+ maxIterations: 2,
75
+ };
76
+
77
+ // Add 20 feedback with low completeness
78
+ for (let i = 0; i < 20; i++) {
79
+ await storage.saveFeedback({
80
+ id: `test-${i}`,
81
+ query: `query ${i}`,
82
+ answer: { text: `answer ${i}`, citations: [], steps: [], rewrites: 0 },
83
+ rating: 3,
84
+ relevance: 0.7,
85
+ completeness: 0.5,
86
+ citationsQuality: 0.8,
87
+ timestamp: new Date(),
88
+ strategy: "strategy-a",
89
+ });
90
+ }
91
+
92
+ const suggestions = await optimizer.analyzeAndSuggest("strategy-a", params);
93
+
94
+ const selfReflectionSuggestion = suggestions.find(s => s.target === "enableSelfReflection");
95
+ expect(selfReflectionSuggestion).toBeDefined();
96
+ expect(selfReflectionSuggestion?.suggested).toBe(true);
97
+ });
98
+
99
+ it("should suggest increasing semanticWeight when citations quality is low", async () => {
100
+ const params: OptimizableParams = {
101
+ semanticWeight: 0.5,
102
+ keywordWeight: 0.5,
103
+ };
104
+
105
+ // Add 20 feedback with low citations quality
106
+ for (let i = 0; i < 20; i++) {
107
+ await storage.saveFeedback({
108
+ id: `test-${i}`,
109
+ query: `query ${i}`,
110
+ answer: { text: `answer ${i}`, citations: [], steps: [], rewrites: 0 },
111
+ rating: 3,
112
+ relevance: 0.7,
113
+ completeness: 0.7,
114
+ citationsQuality: 0.5,
115
+ timestamp: new Date(),
116
+ strategy: "strategy-a",
117
+ });
118
+ }
119
+
120
+ const suggestions = await optimizer.analyzeAndSuggest("strategy-a", params);
121
+
122
+ const semanticWeightSuggestion = suggestions.find(s => s.target === "semanticWeight");
123
+ expect(semanticWeightSuggestion).toBeDefined();
124
+ expect(semanticWeightSuggestion?.suggested).toBeGreaterThan(params.semanticWeight!);
125
+ });
126
+
127
+ it("should apply suggestions with sufficient confidence", () => {
128
+ const currentParams: OptimizableParams = {
129
+ minScore: 0.3,
130
+ topK: 5,
131
+ enableSelfReflection: false,
132
+ };
133
+
134
+ const suggestions = [
135
+ {
136
+ type: "parameter" as const,
137
+ target: "minScore",
138
+ current: 0.3,
139
+ suggested: 0.5,
140
+ expectedImprovement: 0.15,
141
+ confidence: 0.8,
142
+ reasoning: "Test suggestion",
143
+ },
144
+ {
145
+ type: "parameter" as const,
146
+ target: "topK",
147
+ current: 5,
148
+ suggested: 10,
149
+ expectedImprovement: 0.1,
150
+ confidence: 0.6, // Below threshold
151
+ reasoning: "Test suggestion",
152
+ },
153
+ ];
154
+
155
+ const optimized = optimizer.applySuggestions(currentParams, suggestions, 0.7);
156
+
157
+ expect(optimized.minScore).toBe(0.5);
158
+ expect(optimized.topK).toBe(5); // Not applied due to low confidence
159
+ expect(optimized.enableSelfReflection).toBe(false);
160
+ });
161
+
162
+ it("should generate report", async () => {
163
+ const params: OptimizableParams = {
164
+ minScore: 0.5,
165
+ topK: 10,
166
+ };
167
+
168
+ // Add 15 feedback
169
+ for (let i = 0; i < 15; i++) {
170
+ await storage.saveFeedback({
171
+ id: `test-${i}`,
172
+ query: `query ${i}`,
173
+ answer: { text: `answer ${i}`, citations: [], steps: [], rewrites: 0 },
174
+ rating: 4,
175
+ relevance: 0.7,
176
+ completeness: 0.6,
177
+ citationsQuality: 0.8,
178
+ timestamp: new Date(),
179
+ strategy: "strategy-a",
180
+ });
181
+ }
182
+
183
+ const report = await optimizer.generateReport("strategy-a", params);
184
+
185
+ expect(report).toContain("Report Ottimizzazione: strategy-a");
186
+ expect(report).toContain("Metriche Attuali");
187
+ expect(report).toContain("Total Queries");
188
+ expect(report).toContain("15");
189
+ });
190
+
191
+ it("should detect declining trend", async () => {
192
+ const params: OptimizableParams = {
193
+ minScore: 0.5,
194
+ };
195
+
196
+ // Add older feedback with high relevance
197
+ for (let i = 0; i < 10; i++) {
198
+ await storage.saveFeedback({
199
+ id: `old-${i}`,
200
+ query: `query ${i}`,
201
+ answer: { text: `answer ${i}`, citations: [], steps: [], rewrites: 0 },
202
+ rating: 5,
203
+ relevance: 0.9,
204
+ completeness: 0.9,
205
+ citationsQuality: 0.9,
206
+ timestamp: new Date(Date.now() - 1000000),
207
+ strategy: "strategy-a",
208
+ });
209
+ }
210
+
211
+ // Add recent feedback with low relevance
212
+ for (let i = 0; i < 10; i++) {
213
+ await storage.saveFeedback({
214
+ id: `new-${i}`,
215
+ query: `query ${i}`,
216
+ answer: { text: `answer ${i}`, citations: [], steps: [], rewrites: 0 },
217
+ rating: 2,
218
+ relevance: 0.4,
219
+ completeness: 0.4,
220
+ citationsQuality: 0.4,
221
+ timestamp: new Date(),
222
+ strategy: "strategy-a",
223
+ });
224
+ }
225
+
226
+ const suggestions = await optimizer.analyzeAndSuggest("strategy-a", params);
227
+
228
+ const trendSuggestion = suggestions.find(s => s.target === "overall_strategy");
229
+ expect(trendSuggestion).toBeDefined();
230
+ expect(trendSuggestion?.reasoning).toContain("declino");
231
+ });
232
+ });
@@ -0,0 +1,307 @@
1
+ import type { RagFeedback, FeedbackStorage, OptimizationSuggestion } from "./feedback.js";
2
+ import { InMemoryFeedbackStorage } from "./feedback.js";
3
+ import { MetricsCalculator } from "./metrics.js";
4
+
5
+ /**
6
+ * Parametri ottimizzabili per strategie RAG
7
+ */
8
+ export interface OptimizableParams {
9
+ // Corrective RAG
10
+ minGoodHits?: number;
11
+ minScore?: number;
12
+ maxRewrites?: number;
13
+
14
+ // Hybrid Search
15
+ semanticWeight?: number;
16
+ keywordWeight?: number;
17
+ rrfK?: number;
18
+
19
+ // Agentic RAG
20
+ maxIterations?: number;
21
+ enableSelfReflection?: boolean;
22
+ enableChainOfThought?: boolean;
23
+
24
+ // General
25
+ topK?: number;
26
+ }
27
+
28
+ /**
29
+ * Ottimizzatore automatico per parametri RAG
30
+ */
31
+ export class ParameterOptimizer {
32
+ private storage: FeedbackStorage;
33
+
34
+ constructor(storage?: FeedbackStorage) {
35
+ this.storage = storage || new InMemoryFeedbackStorage();
36
+ }
37
+
38
+ /**
39
+ * Analizza i feedback e suggerisce ottimizzazioni
40
+ */
41
+ async analyzeAndSuggest(
42
+ strategy: string,
43
+ currentParams: OptimizableParams
44
+ ): Promise<OptimizationSuggestion[]> {
45
+ const feedbacks = await this.storage.getFeedback(strategy);
46
+
47
+ if (feedbacks.length < 10) {
48
+ return [{
49
+ type: "strategy",
50
+ target: "data_collection",
51
+ current: feedbacks.length,
52
+ suggested: 50,
53
+ expectedImprovement: 0,
54
+ confidence: 1,
55
+ reasoning: `Raccogli almeno 50 feedback per analisi affidabile (attualmente: ${feedbacks.length})`,
56
+ }];
57
+ }
58
+
59
+ const suggestions: OptimizationSuggestion[] = [];
60
+
61
+ // Analizza problemi di relevance
62
+ const relevanceSuggestions = this.analyzeRelevance(feedbacks, currentParams);
63
+ suggestions.push(...relevanceSuggestions);
64
+
65
+ // Analizza problemi di completeness
66
+ const completenessSuggestions = this.analyzeCompleteness(feedbacks, currentParams);
67
+ suggestions.push(...completenessSuggestions);
68
+
69
+ // Analizza problemi di citations quality
70
+ const citationsSuggestions = this.analyzeCitationsQuality(feedbacks, currentParams);
71
+ suggestions.push(...citationsSuggestions);
72
+
73
+ // Analizza trend temporale
74
+ const trendSuggestions = this.analyzeTrend(feedbacks, currentParams);
75
+ suggestions.push(...trendSuggestions);
76
+
77
+ return suggestions;
78
+ }
79
+
80
+ /**
81
+ * Analizza problemi di relevance
82
+ */
83
+ private analyzeRelevance(
84
+ feedbacks: RagFeedback[],
85
+ params: OptimizableParams
86
+ ): OptimizationSuggestion[] {
87
+ const suggestions: OptimizationSuggestion[] = [];
88
+ const avgRelevance = feedbacks.reduce((sum, f) => sum + f.relevance, 0) / feedbacks.length;
89
+
90
+ // Se relevance è bassa, suggerisci di aumentare minScore o topK
91
+ if (avgRelevance < 0.6) {
92
+ if (params.minScore !== undefined && params.minScore < 0.5) {
93
+ suggestions.push({
94
+ type: "parameter",
95
+ target: "minScore",
96
+ current: params.minScore,
97
+ suggested: Math.min(0.7, params.minScore + 0.1),
98
+ expectedImprovement: 0.15,
99
+ confidence: 0.8,
100
+ reasoning: `Relevance media bassa (${avgRelevance.toFixed(2)}). Aumenta minScore per filtrare risultati meno rilevanti.`,
101
+ });
102
+ }
103
+
104
+ if (params.topK !== undefined && params.topK < 10) {
105
+ suggestions.push({
106
+ type: "parameter",
107
+ target: "topK",
108
+ current: params.topK,
109
+ suggested: Math.min(15, params.topK + 3),
110
+ expectedImprovement: 0.1,
111
+ confidence: 0.7,
112
+ reasoning: `Relevance media bassa (${avgRelevance.toFixed(2)}). Aumenta topK per avere più candidati da cui scegliere.`,
113
+ });
114
+ }
115
+ }
116
+
117
+ // Se relevance è molto alta, potresti essere troppo conservativo
118
+ if (avgRelevance > 0.9 && params.minScore !== undefined && params.minScore > 0.7) {
119
+ suggestions.push({
120
+ type: "parameter",
121
+ target: "minScore",
122
+ current: params.minScore,
123
+ suggested: Math.max(0.5, params.minScore - 0.1),
124
+ expectedImprovement: 0.05,
125
+ confidence: 0.6,
126
+ reasoning: `Relevance molto alta (${avgRelevance.toFixed(2)}) ma potresti perdere risultati utili. Riduci minScore per aumentare recall.`,
127
+ });
128
+ }
129
+
130
+ return suggestions;
131
+ }
132
+
133
+ /**
134
+ * Analizza problemi di completeness
135
+ */
136
+ private analyzeCompleteness(
137
+ feedbacks: RagFeedback[],
138
+ params: OptimizableParams
139
+ ): OptimizationSuggestion[] {
140
+ const suggestions: OptimizationSuggestion[] = [];
141
+ const avgCompleteness = feedbacks.reduce((sum, f) => sum + f.completeness, 0) / feedbacks.length;
142
+
143
+ // Se completeness è bassa, suggerisci di abilitare self-reflection o aumentare iterazioni
144
+ if (avgCompleteness < 0.6) {
145
+ if (params.enableSelfReflection === false) {
146
+ suggestions.push({
147
+ type: "parameter",
148
+ target: "enableSelfReflection",
149
+ current: false,
150
+ suggested: true,
151
+ expectedImprovement: 0.2,
152
+ confidence: 0.85,
153
+ reasoning: `Completeness bassa (${avgCompleteness.toFixed(2)}). Abilita self-reflection per migliorare qualità risposte.`,
154
+ });
155
+ }
156
+
157
+ if (params.maxIterations !== undefined && params.maxIterations < 3) {
158
+ suggestions.push({
159
+ type: "parameter",
160
+ target: "maxIterations",
161
+ current: params.maxIterations,
162
+ suggested: Math.min(5, params.maxIterations + 1),
163
+ expectedImprovement: 0.15,
164
+ confidence: 0.75,
165
+ reasoning: `Completeness bassa (${avgCompleteness.toFixed(2)}). Aumenta maxIterations per permettere più tentativi di miglioramento.`,
166
+ });
167
+ }
168
+
169
+ if (params.enableChainOfThought === false) {
170
+ suggestions.push({
171
+ type: "parameter",
172
+ target: "enableChainOfThought",
173
+ current: false,
174
+ suggested: true,
175
+ expectedImprovement: 0.18,
176
+ confidence: 0.8,
177
+ reasoning: `Completeness bassa (${avgCompleteness.toFixed(2)}). Abilita chain-of-thought per risposte più strutturate.`,
178
+ });
179
+ }
180
+ }
181
+
182
+ return suggestions;
183
+ }
184
+
185
+ /**
186
+ * Analizza problemi di citations quality
187
+ */
188
+ private analyzeCitationsQuality(
189
+ feedbacks: RagFeedback[],
190
+ params: OptimizableParams
191
+ ): OptimizationSuggestion[] {
192
+ const suggestions: OptimizationSuggestion[] = [];
193
+ const avgCitations = feedbacks.reduce((sum, f) => sum + f.citationsQuality, 0) / feedbacks.length;
194
+
195
+ // Se citations quality è bassa, suggerisci di migliorare hybrid search
196
+ if (avgCitations < 0.6) {
197
+ if (params.semanticWeight !== undefined && params.semanticWeight < 0.6) {
198
+ suggestions.push({
199
+ type: "parameter",
200
+ target: "semanticWeight",
201
+ current: params.semanticWeight,
202
+ suggested: Math.min(0.7, params.semanticWeight + 0.1),
203
+ expectedImprovement: 0.12,
204
+ confidence: 0.7,
205
+ reasoning: `Citations quality bassa (${avgCitations.toFixed(2)}). Aumenta semanticWeight per risultati più semanticamente rilevanti.`,
206
+ });
207
+ }
208
+
209
+ if (params.rrfK !== undefined && params.rrfK > 80) {
210
+ suggestions.push({
211
+ type: "parameter",
212
+ target: "rrfK",
213
+ current: params.rrfK,
214
+ suggested: Math.max(50, params.rrfK - 20),
215
+ expectedImprovement: 0.1,
216
+ confidence: 0.65,
217
+ reasoning: `Citations quality bassa (${avgCitations.toFixed(2)}). Riduci rrfK per dare più peso ai risultati top-ranked.`,
218
+ });
219
+ }
220
+ }
221
+
222
+ return suggestions;
223
+ }
224
+
225
+ /**
226
+ * Analizza trend temporale
227
+ */
228
+ private analyzeTrend(
229
+ feedbacks: RagFeedback[],
230
+ _params: OptimizableParams
231
+ ): OptimizationSuggestion[] {
232
+ const suggestions: OptimizationSuggestion[] = [];
233
+ const trend = MetricsCalculator.identifyTrend(feedbacks);
234
+
235
+ if (trend === "declining") {
236
+ suggestions.push({
237
+ type: "strategy",
238
+ target: "overall_strategy",
239
+ current: "current",
240
+ suggested: "review",
241
+ expectedImprovement: 0.1,
242
+ confidence: 0.7,
243
+ reasoning: `Trend in declino negli ultimi feedback. Considera di rivedere la strategia o raccogliere feedback qualitativi per capire cosa non funziona.`,
244
+ });
245
+ }
246
+
247
+ return suggestions;
248
+ }
249
+
250
+ /**
251
+ * Applica automaticamente le ottimizzazioni suggerite
252
+ */
253
+ applySuggestions(
254
+ currentParams: OptimizableParams,
255
+ suggestions: OptimizationSuggestion[],
256
+ minConfidence: number = 0.7
257
+ ): OptimizableParams {
258
+ const optimized = { ...currentParams };
259
+
260
+ for (const suggestion of suggestions) {
261
+ if (suggestion.confidence >= minConfidence && suggestion.type === "parameter") {
262
+ (optimized as any)[suggestion.target] = suggestion.suggested;
263
+ }
264
+ }
265
+
266
+ return optimized;
267
+ }
268
+
269
+ /**
270
+ * Genera report di ottimizzazione
271
+ */
272
+ async generateReport(
273
+ strategy: string,
274
+ currentParams: OptimizableParams
275
+ ): Promise<string> {
276
+ const feedbacks = await this.storage.getFeedback(strategy);
277
+ const metrics = MetricsCalculator.calculateMetrics(feedbacks, strategy);
278
+ const suggestions = await this.analyzeAndSuggest(strategy, currentParams);
279
+
280
+ let report = `# Report Ottimizzazione: ${strategy}\n\n`;
281
+ report += `## Metriche Attuali\n`;
282
+ report += `- **Total Queries**: ${metrics.totalQueries}\n`;
283
+ report += `- **Overall Score**: ${metrics.overallScore.toFixed(3)}\n`;
284
+ report += `- **Average Relevance**: ${metrics.averageRelevance.toFixed(3)}\n`;
285
+ report += `- **Average Completeness**: ${metrics.averageCompleteness.toFixed(3)}\n`;
286
+ report += `- **Average Citations Quality**: ${metrics.averageCitationsQuality.toFixed(3)}\n`;
287
+ report += `- **Confidence**: ${(metrics.confidence * 100).toFixed(0)}%\n\n`;
288
+
289
+ report += `## Suggerimenti di Ottimizzazione\n\n`;
290
+
291
+ if (suggestions.length === 0) {
292
+ report += `Nessun suggerimento. I parametri attuali sembrano ottimali.\n`;
293
+ } else {
294
+ for (const suggestion of suggestions) {
295
+ report += `### ${suggestion.target}\n`;
296
+ report += `- **Tipo**: ${suggestion.type}\n`;
297
+ report += `- **Valore attuale**: ${JSON.stringify(suggestion.current)}\n`;
298
+ report += `- **Valore suggerito**: ${JSON.stringify(suggestion.suggested)}\n`;
299
+ report += `- **Miglioramento atteso**: +${(suggestion.expectedImprovement * 100).toFixed(1)}%\n`;
300
+ report += `- **Confidence**: ${(suggestion.confidence * 100).toFixed(0)}%\n`;
301
+ report += `- **Ragionamento**: ${suggestion.reasoning}\n\n`;
302
+ }
303
+ }
304
+
305
+ return report;
306
+ }
307
+ }