Skip to content

Commit

Permalink
Merge branch 'refs/heads/main' into leaderboard-update
Browse files Browse the repository at this point in the history
  • Loading branch information
Layoric committed May 6, 2024
2 parents e1ef357 + 248b297 commit 0454ff0
Show file tree
Hide file tree
Showing 41 changed files with 28,545 additions and 1,968 deletions.
57 changes: 55 additions & 2 deletions MyApp.ServiceInterface/AdminServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
using MyApp.ServiceInterface.Renderers;
using MyApp.ServiceModel;
using ServiceStack;
using ServiceStack.OrmLite;

namespace MyApp.ServiceInterface;

public class AdminServices(AppConfig appConfig, ICommandExecutor executor, UserManager<ApplicationUser> userManager)
public class AdminServices(AppConfig appConfig, ICommandExecutor executor, UserManager<ApplicationUser> userManager,
QuestionsProvider questions)
: Service
{
private static readonly List<string> initUserNames = new()
Expand Down Expand Up @@ -80,4 +82,55 @@ public async Task<object> Any(AdminResetCommonPassword request)

return new AdminResetCommonPasswordResponse { UpdatedUsers = updatedUsers };
}
}

public async Task<object?> Any(ResaveQuestionFromFile request)
{
var post = await questions.GetQuestionFileAsPostAsync(request.Id);
if (post == null)
throw HttpError.NotFound("Post not found");

var refId = $"{request.Id}";
await Db.SaveAsync(post);
var statTotal = await Db.SingleAsync(Db.From<StatTotals>().Where(x => x.Id == refId));
if (statTotal != null)
{
await Db.InsertAsync(new StatTotals
{
Id = refId,
PostId = post.Id,
ViewCount = 0,
FavoriteCount = 0,
UpVotes = 0,
DownVotes = 0,
StartingUpVotes = 0,
CreatedBy = post.CreatedBy,
});
}
appConfig.ResetInitialPostId(Db);
return post;
}

public async Task<object> Any(RankAnswer request)
{
var answer = await questions.GetAnswerAsPostAsync(request.Id);
if (answer == null)
throw HttpError.NotFound("Answer not found");

var answerCreator = !string.IsNullOrEmpty(answer.CreatedBy)
? await Db.ScalarAsync<string>(Db.From<ApplicationUser>().Where(x => x.UserName == answer.CreatedBy).Select(x => x.Id))
: null;

if (answerCreator == null)
throw HttpError.NotFound($"Answer Creator '{answer.CreatedBy}' not found");

MessageProducer.Publish(new AiServerTasks
{
CreateRankAnswerTask = new CreateRankAnswerTask {
AnswerId = answer.RefId!,
UserId = answerCreator,
}
});

return answer;
}
}
87 changes: 87 additions & 0 deletions MyApp.ServiceInterface/AiServer/CreateAnswerCommentTaskCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using AiServer.ServiceModel;
using MyApp.Data;
using MyApp.ServiceModel;
using ServiceStack;

namespace MyApp.ServiceInterface.AiServer;

public class CreateAnswerCommentTaskCommand(AppConfig appConfig) : IAsyncCommand<CreateAnswerCommentTask>
{
public const string SystemPrompt =
"""
You are an IT expert helping a user with a technical issue using your computer science, network infrastructure,
and IT security knowledge to solve my problem using data from StackOverflow, Hacker News, and GitHub of content
like issues submitted, closed issues, number of stars on a repository, and overall StackOverflow activity.
I will provide you with my original question and your initial answer attempt to solve my problem and
my follow up questions asking for further explanation and clarification of your answer.
You should use your expertise to provide specific, concise answers to my follow up questions.
""";

public async Task ExecuteAsync(CreateAnswerCommentTask request)
{
var question = request.Question;

request.AiRef ??= Guid.NewGuid().ToString("N");

var answerPrompt =
$"""
## Original Answer Attempt

{request.Answer.Body}
---
""";

var questionPrompt = CreateAnswerTasksCommand.CreateQuestionPrompt(question);
var openAiChat = new OpenAiChat
{
Model = request.Model,
Messages = [
new() { Role = "system", Content = SystemPrompt },
new() { Role = "user", Content = questionPrompt },
new() { Role = "assistant", Content = answerPrompt },
],
Temperature = 0.2,
MaxTokens = 300,
};

var modelUser = appConfig.GetModelUser(request.Model);
if (modelUser == null)
throw new ArgumentException("Model User not found: " + request.Model);

foreach (var comment in request.Comments)
{
if (comment.CreatedBy == request.UserName)
{
openAiChat.Messages.Add(new() { Role = "user", Content = comment.Body });
}
else if (comment.CreatedBy == modelUser.UserName)
{
openAiChat.Messages.Add(new() { Role = "assistant", Content = comment.Body });
}
}
openAiChat.Messages.Add(new() { Role = "user",
Content = """
## Instruction
Answer my follow up question above in a concise manner.
Keep your response on the topic of the original question and answer, directly addressing my specific comment.
Max 2-3 sentences.
"""
});

var client = appConfig.CreateAiServerClient();

var api = await client.ApiAsync(new CreateOpenAiChat {
RefId = request.AiRef,
Tag = "pvq",
Provider = null,
ReplyTo = appConfig.BaseUrl.CombineWith("api", nameof(AnswerCommentCallback).AddQueryParams(new() {
[nameof(AnswerCommentCallback.AnswerId)] = request.Answer.RefId,
[nameof(AnswerCommentCallback.UserId)] = request.UserId,
[nameof(AnswerCommentCallback.AiRef)] = request.AiRef,
})),
Request = openAiChat
});

api.ThrowIfError();
}
}
53 changes: 42 additions & 11 deletions MyApp.ServiceInterface/AiServer/CreateAnswerTasksCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,35 @@ namespace MyApp.ServiceInterface.AiServer;
public class CreateAnswerTasksCommand(ILogger<CreateAnswerTasksCommand> log,
AppConfig appConfig, QuestionsProvider questions) : IAsyncCommand<CreateAnswerTasks>
{
const string SystemPrompt = "You are a friendly AI Assistant that helps answer developer questions. Think step by step and assist the user with their question, ensuring that your answer is relevant, on topic and provides actionable advice with code examples as appropriate.";
//https://github.com/f/awesome-chatgpt-prompts?tab=readme-ov-file#act-as-an-it-expert
//https://github.com/f/awesome-chatgpt-prompts?tab=readme-ov-file#act-as-a-developer-relations-consultant
public const string SystemPrompt =
"""
You are an IT expert helping a user with a technical issue.
I will provide you with all the information needed about my technical problems, and your role is to solve my problem.
You should use your computer science, network infrastructure, and IT security knowledge to solve my problem
using data from StackOverflow, Hacker News, and GitHub of content like issues submitted, closed issues,
number of stars on a repository, and overall StackOverflow activity.
Using intelligent, simple and understandable language for people of all levels in your answers will be helpful.
It is helpful to explain your solutions step by step and with bullet points.
Try to avoid too many technical details, but use them when necessary.
I want you to reply with the solution, not write any explanations.
""";

public static string CreateQuestionPrompt(Post question)
{
if (string.IsNullOrEmpty(question.Body))
throw new ArgumentNullException(nameof(question.Body));

var content = $$"""
Title: {{question.Title}}

Tags: {{string.Join(", ", question.Tags)}}

{{question.Body}}
""";
return content;
}

public async Task ExecuteAsync(CreateAnswerTasks request)
{
Expand Down Expand Up @@ -44,22 +72,25 @@ public async Task ExecuteAsync(CreateAnswerTasks request)
}

log.LogInformation("Creating Question {Id} OpenAiChat Model for {UserName} to AI Server", question.Id, userName);
var prompt = CreateQuestionPrompt(question);
var openAiChat = new OpenAiChat
{
Model = modelUser.Model!,
Messages = [
new() { Role = "system", Content = SystemPrompt },
new() { Role = "user", Content = prompt },
],
Temperature = 0.7,
MaxTokens = 2048,
};
var response = await client.PostAsync(new CreateOpenAiChat
{
Tag = "pvq",
ReplyTo = appConfig.BaseUrl.CombineWith("api", nameof(CreateAnswerCallback).AddQueryParams(new() {
[nameof(CreateAnswerCallback.PostId)] = question.Id,
[nameof(CreateAnswerCallback.UserId)] = modelUser.Id,
})),
Request = new OpenAiChat
{
Model = modelUser.Model!,
Messages = [
new() { Role = "system", Content = SystemPrompt },
new() { Role = "user", Content = question.Body },
],
Temperature = 0.7,
MaxTokens = 2048,
}
Request = openAiChat
});
}
catch (Exception e)
Expand Down
11 changes: 10 additions & 1 deletion MyApp.ServiceInterface/AiServer/CreateRankAnswerTaskCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ namespace MyApp.ServiceInterface.AiServer;

public class CreateRankAnswerTaskCommand(AppConfig appConfig, QuestionsProvider questions) : IAsyncCommand<CreateRankAnswerTask>
{
//https://github.com/f/awesome-chatgpt-prompts?tab=readme-ov-file#act-as-a-tech-reviewer
public const string SystemPrompt =
"""
I want you to act as a tech reviewer that votes on the quality and relevance of answers to a given question.
I will give you the user's question and the answer that you should review and respond with a score out of 10.
Before giving a score, give a critique of the answer based on quality and relevance to the user's question.
""";

public async Task ExecuteAsync(CreateRankAnswerTask request)
{
var postId = request.AnswerId.LeftPart('-').ToInt();
Expand Down Expand Up @@ -62,6 +70,7 @@ Concisely articulate what a good answer needs to contain and how the answer prov
var client = appConfig.CreateAiServerClient();
var api = await client.ApiAsync(new CreateOpenAiChat {
RefId = Guid.NewGuid().ToString("N"),
Tag = "pvq",
Provider = null,
ReplyTo = appConfig.BaseUrl.CombineWith("api", nameof(RankAnswerCallback).AddQueryParams(new() {
[nameof(RankAnswerCallback.PostId)] = postId,
Expand All @@ -72,7 +81,7 @@ Concisely articulate what a good answer needs to contain and how the answer prov
{
Model = "mixtral",
Messages = [
new() { Role = "system", Content = "You are an AI assistant that votes on the quality and relevance of answers to a given question. Before giving votes, give an critique of each answer based on quality and relevance." },
new() { Role = "system", Content = SystemPrompt },
new() { Role = "user", Content = content },
],
Temperature = 0.1,
Expand Down
Loading

0 comments on commit 0454ff0

Please sign in to comment.