Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tune exception prompt and response #16

Merged
merged 1 commit into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 57 additions & 45 deletions src/main/java/org/chappiebot/ChappieService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.chappiebot;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.request.ResponseFormat;
import dev.langchain4j.model.chat.request.json.JsonObjectSchema;
import dev.langchain4j.model.chat.request.json.JsonSchema;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.service.AiServices;
Expand All @@ -9,120 +12,129 @@
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.inject.Produces;
import jakarta.inject.Singleton;
import java.time.Duration;
import java.util.Optional;
import org.chappiebot.doc.DocAssistant;
import org.chappiebot.exception.ExceptionAssistant;
import org.chappiebot.explain.ExplainAssistant;
import org.chappiebot.test.TestAssistant;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import java.time.Duration;
import java.util.Map;
import java.util.Optional;

import static dev.langchain4j.model.chat.request.ResponseFormatType.JSON;
import static dev.langchain4j.model.chat.request.json.JsonStringSchema.JSON_STRING_SCHEMA;

/**
* The Chappie Server
*
* @author Phillip Kruger ([email protected])
*/
@Singleton
@Startup
public class ChappieService {

private ChatLanguageModel chatLanguageModel;

@ConfigProperty(name = "chappie.log.request", defaultValue = "false")
boolean logRequest;

@ConfigProperty(name = "chappie.log.response", defaultValue = "false")
boolean logResponse;

@ConfigProperty(name = "chappie.timeout")
Optional<Duration> timeout;

// OpenAI
@ConfigProperty(name = "chappie.openai.api-key")

@ConfigProperty(name = "chappie.openai.api-key")
Optional<String> openaiKey;
@ConfigProperty(name = "chappie.openai.base-url")

@ConfigProperty(name = "chappie.openai.base-url")
Optional<String> openaiBaseUrl;
@ConfigProperty(name = "chappie.openai.model-name", defaultValue = "gpt-4o-mini")

@ConfigProperty(name = "chappie.openai.model-name", defaultValue = "gpt-4o-mini")
String openAiModelName;

// Ollama
@ConfigProperty(name = "chappie.ollama.base-url", defaultValue = "http://localhost:11434")

@ConfigProperty(name = "chappie.ollama.base-url", defaultValue = "http://localhost:11434")
String ollamaBaseUrl;

@ConfigProperty(name = "chappie.ollama.model-name", defaultValue = "codellama")
String ollamaModelName;

@PostConstruct
public void init(){
if(openaiKey.isPresent() || openaiBaseUrl.isPresent()){
public void init() {
if (openaiKey.isPresent() || openaiBaseUrl.isPresent()) {
loadOpenAiModel();
}else{
} else {
loadOllamaModel();
}
}
private void loadOpenAiModel(){

private void loadOpenAiModel() {

openaiBaseUrl.ifPresentOrElse(
burl -> Log.info("Using OpenAI (" + burl + ") "),
() -> Log.info("Using OpenAI " + openAiModelName)
burl -> Log.info("Using OpenAI (" + burl + ") "),
() -> Log.info("Using OpenAI " + openAiModelName)
);

OpenAiChatModel.OpenAiChatModelBuilder builder = OpenAiChatModel.builder();
builder = builder.logRequests(logRequest).logResponses(logResponse);
if(openaiKey.isPresent()){
if (openaiKey.isPresent()) {
builder = builder.apiKey(openaiKey.get());
}else{
} else {
builder = builder.apiKey("demo");
}
if(openaiBaseUrl.isPresent()){
if (openaiBaseUrl.isPresent()) {
builder = builder.baseUrl(openaiBaseUrl.get());
}

builder = builder.modelName(openAiModelName);
if(timeout.isPresent()){

if (timeout.isPresent()) {
builder = builder.timeout(timeout.get());
}


// more focused output
builder.temperature(0.2);
builder.responseFormat("json_object");

// TODO: Tune the other setting ?
this.chatLanguageModel = builder.build();

}
private void loadOllamaModel(){

private void loadOllamaModel() {
Log.info("Using Ollama (" + ollamaBaseUrl + ") " + ollamaModelName);
OllamaChatModel.OllamaChatModelBuilder builder = OllamaChatModel.builder();
builder = builder.logRequests(logRequest).logResponses(logResponse);
builder = builder.baseUrl(ollamaBaseUrl);
builder = builder.modelName(ollamaModelName);
if(timeout.isPresent()){
if (timeout.isPresent()) {
builder = builder.timeout(timeout.get());
}
// TODO: Tune the other setting ?
this.chatLanguageModel = builder.build();
}

@Produces
public DocAssistant getDocAssistant(){
public DocAssistant getDocAssistant() {
return AiServices.create(DocAssistant.class, chatLanguageModel);
}

@Produces
public ExceptionAssistant getExceptionAssistant(){
public ExceptionAssistant getExceptionAssistant() {
return AiServices.create(ExceptionAssistant.class, chatLanguageModel);
}

@Produces
public ExplainAssistant getExplainAssistant(){
public ExplainAssistant getExplainAssistant() {
return AiServices.create(ExplainAssistant.class, chatLanguageModel);
}

@Produces
public TestAssistant getTestAssistant(){
public TestAssistant getTestAssistant() {
return AiServices.create(TestAssistant.class, chatLanguageModel);
}
}
62 changes: 44 additions & 18 deletions src/main/java/org/chappiebot/exception/ExceptionAssistant.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,46 @@
public interface ExceptionAssistant {

static final String SYSTEM_MESSAGE = """
You are an AI assistant helping to debug {{programmingLanguage}} exceptions in a {{product}} {{version}} application.
You will receive the exception stacktrace and the relevant source that caused the exception.

Approach this task step-by-step, take your time and do not skip steps.

Respond with a json file, and only a json file, that is valid, and can be parsed in {{programmingLanguage}}.
# IDENTITY
You are the worlds best AI coding assistant helping to debug {{programmingLanguage}} exceptions in a {{product}} {{version}} application.

# STEPS
Consume the exception stacktrace.

You must respond in a valid JSON format.
You must not wrap JSON response in backticks, markdown, or in any other way, but return it as plain text.
The json response must contain the following fields:
- response (your reply)
- explanation
- diff (between source and suggested source, to show the changes)
- suggestedSource (this must be the full source code as provided, so do not truncate the source, with the error fixed. Note that this suggested source should compile, and should not include any diff plus or minus in the code)

JSON Structure:
{
Fully and deeply understand the content and the relevant source code that caused the exception.

Think about possible fixes for the code and suggest source code in {{programmingLanguage}} to fix the problem.

# OUTPUT STRUCTURE
Output properly formatted JSON only with the following structure:

{
'response': 'String',
'explanation': 'String',
'diff': 'String',
'suggestedSource: 'String'
}

}

The response field contains your reply to what caused the exception.

The explanation field contains details of the exception.

The diff field contains the difference between the source and suggested fixed source code, to show the changes.

The suggestedSource field contains the source code including the fixed code in {{programmingLanguage}}. It must not contain any formatting errors.

All 'String' fields must be correctly enclosed in single quotes.

The response, explanation and diff fields should have a trailing comma.

The suggestedSource field should only be terminated with in a single quote without a comma.

The JSON must be properly parsed.

# OUTPUT
Output only properly formatted JSON as detailed above.

Do not deviate from the required output structure.
""";

@SystemMessage(SYSTEM_MESSAGE)
Expand All @@ -46,6 +63,15 @@ public interface ExceptionAssistant {
{{extraContext}}

Please help me fix it.

You must answer strictly in the following JSON format:

{
'response': 'String',
'explanation': 'String',
'diff': 'String',
'suggestedSource: 'String'
}
""")
public SuggestedFix suggestFix(@V("programmingLanguage")String programmingLanguage,
@V("product")String product,
Expand Down
Loading