Skip to content

Commit 0b6268e

Browse files
authored
Merge pull request #18 from learntocloud/addresources
add resources
2 parents b96b1ef + 7916805 commit 0b6268e

File tree

5 files changed

+56
-54
lines changed

5 files changed

+56
-54
lines changed

azure-project-generator/GenerateProject.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,37 +20,37 @@ public GenerateProject(ILogger<GenerateProject> logger, ContentGenerationService
2020
}
2121

2222
[Function("GenerateProject")]
23-
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req, string certificationCode, string skillName,
23+
public async Task<HttpResponseData> Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequestData req, string certificationCode, string skillName, string topic,
2424
[CosmosDBInput(Connection = "CosmosDBConnection")] CosmosClient client)
2525
{
2626
var response = req.CreateResponse(HttpStatusCode.OK);
2727
_logger.LogInformation("C# HTTP trigger function processed a request.");
2828

29-
3029
string projectPrompt = "I need a project idea for the certification exam " + certificationCode + " for the skill " + skillName;
3130

3231
float[] projectPromptVector = _contentGenerationService.GenerateEmbeddingsAsync(projectPrompt).Result;
3332

34-
var queryDef = new QueryDefinition
35-
(query: $"SELECT c.serviceName, c.skillName, c.topicName, VectorDistance(c.contextVector,@embedding) " +
36-
$"AS SimilarityScore FROM c ORDER BY VectorDistance(c.contextVector,@embedding)"
37-
).WithParameter("@embedding", projectPromptVector);
33+
var queryDef = new QueryDefinition(
34+
query: $"SELECT TOP 5 c.serviceName, c.skillName, c.topicName, VectorDistance(c.contextVector, @embedding) " +
35+
$"AS SimilarityScore FROM c ORDER BY VectorDistance(c.contextVector, @embedding)"
36+
).WithParameter("@embedding", projectPromptVector);
3837

3938
using FeedIterator<CertificationService> resultSetIterator =
4039
client.GetContainer("AzureCertDB", "certvectors").GetItemQueryIterator<CertificationService>(queryDef);
4140

42-
string projectServices = "";
41+
List<string> projectServices = new List<string>();
4342

4443
while (resultSetIterator.HasMoreResults)
4544
{
4645
FeedResponse<CertificationService> feedResponse = resultSetIterator.ReadNextAsync().Result;
4746
foreach (var item in feedResponse)
4847
{
49-
projectServices += item.ServiceName + " ";
48+
projectServices.Add(item.ServiceName);
5049
}
5150
}
5251

53-
string cloudProjectIdea = await _contentGenerationService.GenerateProjectIdeaAsync(projectServices, skillName);
52+
string cloudProjectIdea = await _contentGenerationService.GenerateProjectIdeaAsync(projectServices, skillName, topic);
53+
5454

5555
response.Headers.Add("Content-Type", "application/json");
5656
await response.WriteStringAsync(cloudProjectIdea);

azure-project-generator/ProcessCertServiceFile.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ public async Task<CertificationServiceOutput> Run(
3535
if (string.IsNullOrWhiteSpace(content))
3636
{
3737
_logger.LogError("Blob content is empty or whitespace.");
38-
return new CertificationServiceOutput { Document = null, ArchivedContent = null };
38+
return new CertificationServiceOutput { Document = null};
3939
}
4040

4141
if (!_jsonValidationService.ValidateJsonContent<CertificationService>(content))
4242
{
43-
return new CertificationServiceOutput { Document = null, ArchivedContent = null };
43+
return new CertificationServiceOutput { Document = null };
4444
}
4545

4646
var mappedServiceData = JsonConvert.DeserializeObject<CertificationService>(content);
4747
if (mappedServiceData == null)
4848
{
4949
_logger.LogError("Failed to deserialize content to MappedService.");
50-
return new CertificationServiceOutput { Document = null, ArchivedContent = null };
50+
return new CertificationServiceOutput { Document = null };
5151
}
5252

5353
string contextSentence = _contentGenerationService.GenerateCertServiceContextSentence(mappedServiceData);
@@ -62,7 +62,7 @@ public async Task<CertificationServiceOutput> Run(
6262
return new CertificationServiceOutput
6363
{
6464
Document = certServiceDocument,
65-
ArchivedContent = content
65+
6666
};
6767
}
6868

azure-project-generator/models/CertificationServiceOutput.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,5 @@ public class CertificationServiceOutput
1313
[CosmosDBOutput("%CosmosDb%", "%CertificationServiceOut%", Connection = "CosmosDBConnection")]
1414
public CertificationServiceDocument Document { get; set; }
1515

16-
[BlobOutput("certservicearchive/{name}", Connection = "AzureWebJobsStorage")]
17-
public string ArchivedContent { get; set; }
18-
1916
}
2017
}

azure-project-generator/models/CloudProjectIdea.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ namespace azure_project_generator.models
88
{
99
public class CloudProjectIdea
1010
{
11-
12-
public string Title { get; set; }
13-
public string Description { get; set; }
14-
public List<string> Steps { get; set; }
15-
11+
public string Title { get; set; }
12+
public string Description { get; set; }
13+
public List<string> Steps { get; set; }
14+
public List<string> Resources { get; set; }
15+
16+
// Constructor to initialize Resources
17+
public CloudProjectIdea()
18+
{
19+
Resources = new List<string>();
20+
}
1621
}
1722
}

azure-project-generator/services/ContentGenerationService.cs

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using Microsoft.Extensions.Logging;
44
using OpenAI.Embeddings;
55
using OpenAI.Chat;
6-
using Newtonsoft.Json.Linq;
6+
using Newtonsoft.Json;
77

88
namespace azure_project_generator.services
99
{
@@ -45,34 +45,33 @@ public async Task<float[]> GenerateEmbeddingsAsync(string content)
4545
}
4646
}
4747

48-
public async Task<string> GenerateProjectIdeaAsync(string services, string skill)
48+
public async Task<string> GenerateProjectIdeaAsync(List<string> services, string skill, string topic)
4949
{
50-
string userPrompt = $@"You are an expert cloud architect.
51-
Please generate a detailed project idea for a beginner-friendly weekend cloud solution
52-
based on the following Azure certification skill: {skill}.
53-
The project should utilize the ONLY following services: {services}.
54-
The project should be small in scale, achievable over a weekend, and have a fun, creative name. Suitable for beginners. Cheap to run.
55-
The response must be formatted as valid JSON and include only the following fields:
56-
{{
57-
""projectName"": ""A fun and creative project name"",
58-
""description"": ""A brief, engaging description of the project, highlighting its purpose and main features."",
59-
""learningGoals"": [""Goal 1"", ""Goal 2"", ""Goal 3""],
60-
""steps"": [
61-
""Step 1: Description of the first step"",
62-
""Step 2: Description of the second step"",
63-
""Step 3: Description of the third step"",
64-
""Step 4: Description of the fourth step"",
65-
""Step 5: Description of the fifth step""
66-
]
67-
}}
68-
Ensure that the project idea is practical, aligned with beginner-level skills, and leverages best practices in Azure architecture. Small in scope";
50+
string userPrompt = $@"You are a cloud architect specializing in Azure architecture.
51+
Please generate a detailed project idea for a small, practical cloud solution based on the following Azure certification skill: {skill} and topic: {topic}.
52+
The project should utilize ONLY the following services: {services}.
53+
The project should focus on key technical steps without any subjective descriptions or recommendations.
54+
The response must be formatted as valid JSON and include only the following fields:
55+
{{
56+
""title"": ""A concise, descriptive project name"",
57+
""description"": ""A factual description of the project, highlighting its technical purpose and main features."",
58+
""steps"": [
59+
""Step 1: Description of the first technical step"",
60+
""Step 2: Description of the second technical step"",
61+
""Step 3: Description of the third technical step"",
62+
""Step 4: Description of the fourth technical step"",
63+
""Step 5: Description of the fifth technical step""
64+
]
65+
}}
66+
Ensure that the project idea is focused purely on technical details, aligned with best practices in Azure architecture, and small in scope.";
6967

7068
try
7169
{
7270
_logger.LogInformation("Generating project idea...");
7371
ChatCompletion completion = await _completionsClient.CompleteChatAsync(new ChatMessage[]
7472
{
75-
new SystemChatMessage("You are a technical assistant specialized in generating beginner-friendly cloud project ideas. Provide the response in JSON format only, without any additional text."),
73+
new SystemChatMessage("You are a cloud engineer and mentor specialized in generating " +
74+
"beginner-friendly cloud project ideas. Provide the response in JSON format only, without any additional text."),
7675
new UserChatMessage(userPrompt)
7776
});
7877

@@ -90,21 +89,22 @@ public async Task<string> GenerateProjectIdeaAsync(string services, string skill
9089
.Replace("json\n", string.Empty)
9190
.Trim();
9291

93-
JObject jsonObject = JObject.Parse(cleanedJsonContent);
92+
// deserialize to CloudProjectIdea object
9493

95-
// Validate that all required fields are present
96-
string[] requiredFields = { "projectName", "description", "learningGoals", "steps"};
97-
foreach (var field in requiredFields)
94+
CloudProjectIdea cloudProjectIdea = JsonConvert.DeserializeObject<CloudProjectIdea>(cleanedJsonContent);
95+
foreach (var service in services)
9896
{
99-
if (!jsonObject.ContainsKey(field))
100-
{
101-
_logger.LogWarning($"Generated JSON is missing required field: {field}");
102-
throw new System.Text.Json.JsonException($"Generated project idea is missing required field: {field}");
97+
// Properly encode the skill, topic, and service
98+
string encodedTopic = System.Net.WebUtility.UrlEncode(topic);
99+
string encodedService = System.Net.WebUtility.UrlEncode(service);
103100

104-
}
101+
// Construct the URL using the encoded values
102+
cloudProjectIdea.Resources.Add($"https://learn.microsoft.com/search/?terms={encodedTopic}%20{encodedService}&category=Training");
105103
}
106104

107-
return jsonObject.ToString();
105+
string jsonString = JsonConvert.SerializeObject(cloudProjectIdea);
106+
107+
return jsonString;
108108
}
109109
catch (System.Text.Json.JsonException ex)
110110
{
@@ -123,4 +123,4 @@ public async Task<string> GenerateProjectIdeaAsync(string services, string skill
123123
}
124124
}
125125
}
126-
}
126+
}

0 commit comments

Comments
 (0)