forked from OpenAI-VeniceAI-PMLL/pmll
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAI.cs
457 lines (398 loc) · 17.8 KB
/
AI.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;
using OpenAI_API;
namespace CopilotAzureChatGPT5o
{
public static class AIAgentOrchestrator
{
[FunctionName("AIAgentOrchestrator")]
public static async Task Run(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
// Retrieve short-term memory (STM) or initialize
var shortTermMemory = context.GetInput<List<string>>() ?? new List<string>();
// Wait for a new novel input via an external event
string novelInput = await context.WaitForExternalEvent<string>("NovelInput");
shortTermMemory.Add(novelInput);
log.LogInformation($"[Orchestrator] Received novel input: {novelInput}");
// Process the input using OpenAI via an activity function
string openAiResponse = await context.CallActivityAsync<string>("ProcessNovelInputActivity", novelInput);
log.LogInformation($"[Orchestrator] OpenAI response: {openAiResponse}");
// Check if STM needs to be consolidated into LTM
if (shortTermMemory.Count >= 5 || context.CurrentUtcDateTime.Subtract(context.StartTime).TotalMinutes >= 10)
{
await context.CallActivityAsync("ConsolidateMemory", shortTermMemory);
log.LogInformation("[Orchestrator] STM consolidated into LTM.");
shortTermMemory.Clear();
}
// Prevent excessive history buildup by using ContinueAsNew
context.ContinueAsNew(shortTermMemory);
}
}
public static class ProcessNovelInputActivity
{
[FunctionName("ProcessNovelInputActivity")]
public static async Task<string> Run(
[ActivityTrigger] string novelInput,
ILogger log)
{
string apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
if (string.IsNullOrEmpty(apiKey))
{
log.LogError("OpenAI API key is not set in environment variables.");
return "Error: No API key";
}
var openAiClient = new OpenAIAPI(apiKey);
var completionRequest = new OpenAI_API.Completions.CompletionRequest
{
Prompt = $"Process this input and provide insights: {novelInput}",
MaxTokens = 100,
Temperature = 0.7
};
try
{
var result = await openAiClient.Completions.CreateCompletionAsync(completionRequest);
string response = result.Completions?[0].Text.Trim() ?? "No response";
log.LogInformation($"[ProcessNovelInputActivity] Processed input: {novelInput} | Response: {response}");
return response;
}
catch (Exception ex)
{
log.LogError($"[ProcessNovelInputActivity] OpenAI API error: {ex.Message}");
return "Error processing input";
}
}
}
public static class ConsolidateMemory
{
[FunctionName("ConsolidateMemory")]
public static async Task Run(
[ActivityTrigger] List<string> memoryBatch,
ILogger log)
{
log.LogInformation("[ConsolidateMemory] Consolidating STM into LTM.");
foreach (var item in memoryBatch)
{
log.LogInformation($" - {item}");
}
await Task.Delay(500); // Simulate database write
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;
using Azure.Data.Tables;
using System.Linq;
using OpenAI_API;
namespace CopilotAzureChatGPT5o
{
public static class SelfLearningAI
{
private const string TableName = "AIMemoryTable";
private static TableClient _tableClient;
[FunctionName("InitializeMemory")]
public static async Task InitializeMemory([TimerTrigger("0 */30 * * * *")] TimerInfo myTimer, ILogger log)
{
var connectionString = Environment.GetEnvironmentVariable("AZURE_STORAGE_CONNECTION_STRING");
_tableClient = new TableClient(connectionString, TableName);
await _tableClient.CreateIfNotExistsAsync();
log.LogInformation("[Memory] AI Memory Initialized.");
}
[FunctionName("StoreMemory")]
public static async Task StoreMemory([ActivityTrigger] MemoryEntry memory, ILogger log)
{
await _tableClient.AddEntityAsync(memory);
log.LogInformation($"[Memory] Stored: {memory.Input} → {memory.Response}");
}
[FunctionName("RetrieveMemory")]
public static async Task<List<MemoryEntry>> RetrieveMemory([ActivityTrigger] string query, ILogger log)
{
var results = _tableClient.QueryAsync<MemoryEntry>(m => m.Input.Contains(query));
List<MemoryEntry> memoryEntries = new();
await foreach (var entry in results) memoryEntries.Add(entry);
log.LogInformation($"[Memory] Retrieved {memoryEntries.Count} relevant memories.");
return memoryEntries;
}
[FunctionName("ProcessUserQuery")]
public static async Task<string> ProcessUserQuery([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
string userInput = context.GetInput<string>();
log.LogInformation($"[AI] Processing input: {userInput}");
// Retrieve past similar queries from memory
var previousResponses = await context.CallActivityAsync<List<MemoryEntry>>("RetrieveMemory", userInput);
if (previousResponses.Any())
{
var bestMatch = previousResponses.OrderByDescending(m => m.Timestamp).First();
log.LogInformation($"[Memory] Found past response: {bestMatch.Response}");
return bestMatch.Response;
}
// No memory match, call OpenAI API
string aiResponse = await context.CallActivityAsync<string>("ProcessWithOpenAI", userInput);
log.LogInformation($"[AI] OpenAI Response: {aiResponse}");
// Store new knowledge
var newMemory = new MemoryEntry { PartitionKey = "AI_Memory", RowKey = Guid.NewGuid().ToString(), Input = userInput, Response = aiResponse };
await context.CallActivityAsync("StoreMemory", newMemory);
return aiResponse;
}
[FunctionName("ProcessWithOpenAI")]
public static async Task<string> ProcessWithOpenAI([ActivityTrigger] string input, ILogger log)
{
string apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
if (string.IsNullOrEmpty(apiKey))
{
log.LogError("OpenAI API key is missing.");
return "Error: No API key.";
}
var openAiClient = new OpenAIAPI(apiKey);
var completionRequest = new OpenAI_API.Completions.CompletionRequest
{
Prompt = $"Learn from the following input and respond: {input}",
MaxTokens = 100,
Temperature = 0.7
};
try
{
var result = await openAiClient.Completions.CreateCompletionAsync(completionRequest);
string response = result.Completions?[0].Text.Trim() ?? "No response";
log.LogInformation($"[AI] Generated response: {response}");
return response;
}
catch (Exception ex)
{
log.LogError($"[AI] OpenAI API error: {ex.Message}");
return "Error processing input.";
}
}
}
public class MemoryEntry : ITableEntity
{
public string PartitionKey { get; set; }
public string RowKey { get; set; }
public string Input { get; set; }
public string Response { get; set; }
public DateTimeOffset Timestamp { get; set; }
public string ETag { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Azure.AI.TextAnalytics;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;
namespace CopilotAzureChatGPT5o
{
public static class EmotionMemory
{
private static readonly string _textAnalyticsKey = Environment.GetEnvironmentVariable("TEXT_ANALYTICS_KEY");
private static readonly string _textAnalyticsEndpoint = Environment.GetEnvironmentVariable("TEXT_ANALYTICS_ENDPOINT");
private static readonly TextAnalyticsClient _client = new(
new Uri(_textAnalyticsEndpoint),
new AzureKeyCredential(_textAnalyticsKey)
);
[FunctionName("AnalyzeSentiment")]
public static async Task<string> AnalyzeSentiment([ActivityTrigger] string message, ILogger log)
{
DocumentSentiment sentiment = await _client.AnalyzeSentimentAsync(message);
string emotion = sentiment.Sentiment.ToString();
log.LogInformation($"[Sentiment] Message: '{message}' → Emotion: {emotion}");
return emotion;
}
[FunctionName("StoreEmotionMemory")]
public static async Task StoreEmotionMemory([ActivityTrigger] MemoryEntry memory, ILogger log)
{
memory.Sentiment = await AnalyzeSentiment(memory.Input, log);
await GraphMemory.StoreGraphMemory(memory, log);
log.LogInformation($"[Memory] Stored sentiment-based memory: {memory.Input} → {memory.Response} [Sentiment: {memory.Sentiment}]");
}
}
}
using System;
using System.Threading.Tasks;
using Azure.AI.TextAnalytics;
using Azure.AI.Speech;
using Azure.AI.Speech.Audio;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
namespace CopilotAzureChatGPT5o
{
public static class VoiceAI
{
private static readonly string _speechKey = Environment.GetEnvironmentVariable("SPEECH_KEY");
private static readonly string _speechRegion = Environment.GetEnvironmentVariable("SPEECH_REGION");
private static readonly SpeechConfig _speechConfig = SpeechConfig.FromSubscription(_speechKey, _speechRegion);
[FunctionName("SpeechToText")]
public static async Task<string> SpeechToText([ActivityTrigger] byte[] audioData, ILogger log)
{
using var audioInput = AudioDataStream.FromResult(audioData);
using var recognizer = new SpeechRecognizer(_speechConfig, AudioConfig.FromStreamInput(audioInput));
var result = await recognizer.RecognizeOnceAsync();
log.LogInformation($"[STT] Recognized: {result.Text}");
return result.Text;
}
[FunctionName("TextToSpeech")]
public static async Task<byte[]> TextToSpeech([ActivityTrigger] string text, ILogger log)
{
using var synthesizer = new SpeechSynthesizer(_speechConfig, null);
var result = await synthesizer.SpeakTextAsync(text);
log.LogInformation($"[TTS] Synthesized Speech for: {text}");
return result.AudioData;
}
}
}
public static class PersonalizedAI
{
[FunctionName("FineTunedResponse")]
public static async Task<string> FineTunedResponse([ActivityTrigger] string input, ILogger log)
{
string apiKey = Environment.GetEnvironmentVariable("OPENAI_API_KEY");
string fineTunedModel = Environment.GetEnvironmentVariable("OPENAI_FINE_TUNED_MODEL");
var openAiClient = new OpenAIAPI(apiKey);
var completionRequest = new OpenAI_API.Completions.CompletionRequest
{
Model = fineTunedModel,
Prompt = input,
MaxTokens = 100,
Temperature = 0.7
};
try
{
var result = await openAiClient.Completions.CreateCompletionAsync(completionRequest);
return result.Completions?[0].Text.Trim() ?? "No response";
}
catch (Exception ex)
{
log.LogError($"[Fine-Tuned AI] Error: {ex.Message}");
return "Error processing input.";
}
}
}
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using Neo4j.Driver;
namespace CopilotAzureChatGPT5o
{
public static class GraphMemory
{
private static readonly string Neo4jUri = Environment.GetEnvironmentVariable("NEO4J_URI");
private static readonly string Neo4jUser = Environment.GetEnvironmentVariable("NEO4J_USER");
private static readonly string Neo4jPassword = Environment.GetEnvironmentVariable("NEO4J_PASSWORD");
private static IDriver _driver = GraphDatabase.Driver(Neo4jUri, AuthTokens.Basic(Neo4jUser, Neo4jPassword));
[FunctionName("StoreGraphMemory")]
public static async Task StoreGraphMemory([ActivityTrigger] MemoryEntry memory, ILogger log)
{
await using var session = _driver.AsyncSession();
await session.WriteTransactionAsync(async tx =>
{
await tx.RunAsync("MERGE (m:Memory {input: $input}) SET m.response = $response",
new { input = memory.Input, response = memory.Response });
});
log.LogInformation($"[GraphMemory] Stored knowledge in Neo4j: {memory.Input} → {memory.Response}");
}
[FunctionName("RetrieveGraphMemory")]
public static async Task<string> RetrieveGraphMemory([ActivityTrigger] string query, ILogger log)
{
await using var session = _driver.AsyncSession();
var result = await session.ReadTransactionAsync(async tx =>
{
var reader = await tx.RunAsync("MATCH (m:Memory) WHERE m.input CONTAINS $query RETURN m.response LIMIT 1",
new { query });
var record = await reader.SingleAsync();
return record["m.response"].As<string>();
});
log.LogInformation($"[GraphMemory] Retrieved knowledge for '{query}': {result}");
return result;
}
}
public static class MultiTurnMemory
{
private static Dictionary<string, List<string>> _sessionMemory = new();
[FunctionName("StoreUserSession")]
public static void StoreUserSession([ActivityTrigger] string userId, string message, ILogger log)
{
if (!_sessionMemory.ContainsKey(userId))
_sessionMemory[userId] = new List<string>();
_sessionMemory[userId].Add(message);
log.LogInformation($"[Session] Stored message for {userId}: {message}");
}
[FunctionName("RetrieveUserSession")]
public static List<string> RetrieveUserSession([ActivityTrigger] string userId, ILogger log)
{
if (_sessionMemory.TryGetValue(userId, out var messages))
{
log.LogInformation($"[Session] Retrieved session for {userId}: {string.Join(", ", messages)}");
return messages;
}
log.LogInformation($"[Session] No session found for {userId}");
return new List<string>();
}
using System;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
public static class WebSocketHandler
{
private static Dictionary<string, WebSocket> _activeSockets = new();
[FunctionName("WebSocketHandler")]
public static async Task WebSocketFunction([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req,
ILogger log)
{
if (!req.HttpContext.WebSockets.IsWebSocketRequest)
{
log.LogError("Invalid WebSocket request.");
return;
}
var socket = await req.HttpContext.WebSockets.AcceptWebSocketAsync();
string connectionId = Guid.NewGuid().ToString();
_activeSockets[connectionId] = socket;
log.LogInformation($"WebSocket connection established: {connectionId}");
await HandleWebSocketConnection(socket, connectionId, log);
}
private static async Task HandleWebSocketConnection(WebSocket socket, string connectionId, ILogger log)
{
var buffer = new byte[1024 * 4];
while (socket.State == WebSocketState.Open)
{
var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Close)
{
log.LogInformation($"WebSocket {connectionId} closed.");
_activeSockets.Remove(connectionId);
await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Session Ended", CancellationToken.None);
}
else
{
string receivedMessage = Encoding.UTF8.GetString(buffer, 0, result.Count);
log.LogInformation($"Received message: {receivedMessage}");
// Process the input and send back AI-generated response
string aiResponse = await GenerateAIResponse(receivedMessage, log);
var responseBuffer = Encoding.UTF8.GetBytes(aiResponse);
await socket.SendAsync(new ArraySegment<byte>(responseBuffer, 0, responseBuffer.Length),
WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
private static async Task<string> GenerateAIResponse(string message, ILogger log)
{
return await Task.FromResult($"AI Response: {message} (processed in real-time)");
}
}