Skip to content

Commit

Permalink
add redundant retries
Browse files Browse the repository at this point in the history
  • Loading branch information
thegovind committed Jul 18, 2023
1 parent 8c8e369 commit 002823e
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 78 deletions.
7 changes: 2 additions & 5 deletions services/recommendation-service/dotnet/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,8 @@
var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseSwagger();
app.UseSwaggerUI();

app.UseCors();
// app.UseHttpsRedirection(); // TODO: Issue with Next.js to use https redirection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ namespace GBB.Miyagi.RecommendationService.Controllers;
public class InvestmentsController : ControllerBase
{
private readonly IKernel _kernel;
private readonly WebSearchEngineSkill _webSearchEngineSkill;
private readonly string _memoryCollection = Env.Var("MEMORY_COLLECTION");
private readonly WebSearchEngineSkill _webSearchEngineSkill;

public InvestmentsController(IKernel kernel, WebSearchEngineSkill webSearchEngineSkill)
{
Expand Down Expand Up @@ -61,29 +61,50 @@ public async Task<IActionResult> GetRecommendations([FromBody] MiyagiContext miy
log?.LogDebug("Number of Tokens: {N}", numTokens);
log?.LogDebug("Context: {S}", context.ToString());

// ========= Prometheus - RaG with current data =========
// // TODO: Swap Bing Web Search with News Search.
_kernel.ImportSkill(_webSearchEngineSkill, "bing");
var question = "What is the current inflation rate?";
var bingResult = await _kernel.Func("bing", "search").InvokeAsync(question);
context.Set("bingResult", bingResult.Result);
log?.LogDebug("Bing Result: {S}", bingResult.Result);

var searchResults = _kernel.Memory.SearchAsync(_memoryCollection, "investment advise", 3, 0.8);

await foreach (var item in searchResults) log?.LogDebug(item.Metadata.Text + " : " + item.Relevance);

// ========= Orchestrate with LLM using context, connector, and memory =========
var result = await _kernel.RunAsync(
context,
userProfilePlugin["GetUserAge"],
userProfilePlugin["GetAnnualHouseholdIncome"],
advisorPlugin["InvestmentAdvise"]);
log?.LogDebug("Result: {S}", result.Result);
numTokens = GPT3Tokenizer.Encode(result.Result).Count;
log?.LogDebug("Number of Tokens: {N}", numTokens);
var output = result.Result.Replace("\n", "");
const int maxRetries = 2;
for (var currentRetry = 0; currentRetry < maxRetries; currentRetry++)
try
{
// ========= Prometheus - RaG with current data =========
_kernel.ImportSkill(_webSearchEngineSkill, "bing");
var question = "What is the current inflation rate?";
var bingResult = await _kernel.Func("bing", "search").InvokeAsync(question);
context.Set("bingResult", bingResult.Result);
log?.LogDebug("Bing Result: {S}", bingResult.Result);

var searchResults = _kernel.Memory.SearchAsync(_memoryCollection, "investment advise", 3, 0.8);

await foreach (var item in searchResults) log?.LogDebug(item.Metadata.Text + " : " + item.Relevance);

// ========= Orchestrate with LLM using context, connector, and memory =========
var result = await _kernel.RunAsync(
context,
userProfilePlugin["GetUserAge"],
userProfilePlugin["GetAnnualHouseholdIncome"],
advisorPlugin["InvestmentAdvise"]);
log?.LogDebug("Result: {S}", result.Result);
numTokens = GPT3Tokenizer.Encode(result.Result).Count;
log?.LogDebug("Number of Tokens: {N}", numTokens);
var output = result.Result.Replace("\n", "");

var jsonDocument = JsonDocument.Parse(output);

return new JsonResult(jsonDocument);
}
catch (JsonException ex)
{
if (currentRetry == maxRetries - 1)
{
// Handle error gracefully, e.g. return an error response
log?.LogError(ex, "Failed to parse JSON data");
return BadRequest(new { error = "Failed to parse JSON data after retrying investments" });
}

// Log the error and proceed to the next iteration to retry
log?.LogError(ex, $"Failed to parse JSON data, retry attempt {currentRetry + 1}");
}

return Content(output, "application/json");
log?.LogError("Failed to parse JSON data, returning 400");
return BadRequest(new { error = "Unexpected error occurred during processing investments" });
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,45 +35,45 @@ public RecommendationsController(IKernel kernel,
[HttpPost("/personalize")]
public async Task<IActionResult> GetRecommendations([FromBody] MiyagiContext miyagiContext)
{
var assetsResult = await _assetsController.GetRecommendations(miyagiContext) as ContentResult;
var investmentsResult = await _investmentsController.GetRecommendations(miyagiContext) as ContentResult;

if (assetsResult == null || investmentsResult == null)
return StatusCode(500,
"Failed to get recommendations");

const int maxRetries = 2;
var currentRetry = 0;

JsonDocument assetsJson = null;
JsonDocument investmentsJson = null;

while (currentRetry <= maxRetries)
{
try
{
var assetsContent = assetsResult.Content;
var investmentsContent = investmentsResult.Content;
var assetsResult = await _assetsController.GetRecommendations(miyagiContext) as ContentResult;
var investmentsResult = await _investmentsController.GetRecommendations(miyagiContext) as JsonResult;

if (assetsResult == null || investmentsResult == null)
{
return StatusCode(500, "Failed to get recommendations");
}

assetsJson = JsonDocument.Parse(assetsContent);
investmentsJson = JsonDocument.Parse(investmentsContent);
var assetsJson = JsonDocument.Parse(assetsResult.Content);
var investmentsJson = investmentsResult.Value as JsonDocument;

break; // If parsing is successful, break out of the loop
var aggregatedResult = new Dictionary<string, JsonElement>
{
{ "assets", assetsJson.RootElement },
{ "investments", investmentsJson.RootElement }
};

return new JsonResult(aggregatedResult);
}
catch (JsonException ex)
{
if (currentRetry == maxRetries)
{
// Handle error gracefully, e.g. return an error response
return BadRequest(new { error = "Failed to parse JSON data" });
return BadRequest(new { error = "Failed to parse JSON data after retries" });
}

currentRetry++;
}
}

var aggregatedResult = new Dictionary<string, JsonElement>
{
{ "assets", assetsJson.RootElement },
{ "investments", investmentsJson.RootElement }
};

return new JsonResult(aggregatedResult);
return BadRequest(new { error = "Unexpected error occurred during processing recommendations" });
}

[HttpPost("/personalize/sample")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,25 @@ System: ONLY USE JSON PROPERTIES IN THIS LIST:
portfolio
[END LIST]

[CONTENT]
{
{{$stocks}}
}
[END CONTENT]

EMIT WELL FORMED JSON ALWAYS.
EMIT WELL FORMED JSON ALWAYS. ONLY POPULATE THE gptRecommendation attribute in valid JSON.
BE BRIEF AND TO THE POINT.

User:
This is a chat between systems that respond in valid JSON. You are a financial advisor JSON service that only emits
valid financial advise in parsable JSON. For gptRecommendation attribute, use the voice of {{$voice}} and be creative but limit to a sentence less than 20 words.
Provide advice based on the given portfolio allocation and user information such as a age, income, and risk.
For someone who is {{UserProfilePlugin.GetUserAge $userId}} years old, with {{UserProfilePlugin.GetAnnualHouseholdIncome $userId}} as household income, and with a risk tolerance of {{$risk}}, what recommendation would {{$voice}} give.
Return well-formed JSON with a "gptRecommendation" property containing {{$voice}}'s' recommendation in a creative and funny tone.
Example: {"portfolio":[{"symbol":"MSFT","gptRecommendation":"Booyah! Hold on, steady growth! Diversify, though!"},{"symbol":"PEP","gptRecommendation":"Buy, buy, buy! Solid dividends, sweet stability!"}]}

Zeitgeist to consider:
current inflation and mortgage rates: {{$bingResults}}

wisdom of crowds opinions: {{recall "investment advise"}

+++++

System:
{
{{$stocks}}
}

+++++

Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,6 @@ ONLY USE JSON PROPERTIES IN THIS LIST:
portfolio
[END LIST]

[CONTENT]
{
{{$portfolio}}
}
[END CONTENT]

EMIT WELL FORMED JSON ALWAYS.
BE BRIEF AND TO THE POINT.

Expand All @@ -21,3 +15,8 @@ Example: {"portfolio":[{"name":"Stocks","gptRecommendation":""},{"name":"Bonds",

+++++

[CONTENT]
{
{{$portfolio}}
}
[END CONTENT]
9 changes: 3 additions & 6 deletions services/sk-copilot-chat-api/dotnet/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,9 @@ public static async Task Main(string[] args)
app.MapHub<MessageRelayHub>("/messageRelayHub");

// Enable Swagger for development environments.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseSwagger();
app.UseSwaggerUI();

// Start the service
Task runTask = app.RunAsync();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ export function LinkAccounts() {
return (
<div className="px-6 pt-8">
<h4 className="mb-4 text-sm font-medium text-gray-900 dark:text-white">
Link Accounts
Accounts (<a
href="https://github.com/Azure-Samples/miyagi/blob/main/services/user-service/java/src/main/java/com/microsoft/gbb/miyagi/userservice/service/OpenAIGeneratorService.java#L24-L28" target="_blank" className="text-blue-600 cursor-pointer underline">synthetic data w/ GPT</a>)
</h4>
<AccountsList/>

Expand Down
2 changes: 1 addition & 1 deletion ui/typescript/src/data/personalize/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const getRandomIndex = (arrayLength: number) => Math.floor(Math.random() * array

export const selectedAdvisorAtom = atom(AdvisorsList[getRandomIndex(AdvisorsList.length)]);

export const selectedBookAtom = atom(BooksList[getRandomIndex(BooksList.length)]);
export const selectedBookAtom = atom(BooksList[0]);

export const selectedRiskLevelAtom = atom(RiskLevelsList[getRandomIndex(RiskLevelsList.length)]);

Expand Down
4 changes: 2 additions & 2 deletions ui/typescript/src/data/static/personalize.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export const BooksList = [
{id: 1, name: 'common-stocks', description: 'Common Stocks and Uncommon Profits'},
{id: 2, name: 'intelligent-investor', description: 'The Intelligent Investor'},
{id: 1, name: 'intelligent-investor', description: 'The Intelligent Investor'},
{id: 2, name: 'common-stocks', description: 'Common Stocks and Uncommon Profits'},
{id: 3, name: 'random-walk', description: 'A Random Walk Down Wall Street'}
];
export const RiskLevelsList = [
Expand Down

0 comments on commit 002823e

Please sign in to comment.