Skip to content

Commit

Permalink
Merge pull request #283 from dRAGon-Okinawa/farm-silo-routing
Browse files Browse the repository at this point in the history
Farm Silo Routing
  • Loading branch information
amengus87 authored Sep 26, 2024
2 parents 7ed88dc + 082a07c commit b60d8b1
Show file tree
Hide file tree
Showing 50 changed files with 1,024 additions and 144 deletions.
18 changes: 18 additions & 0 deletions .devcontainer/motd.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
BLACK='\033[0;30m'
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
PURPLE='\033[0;35m'
CYAN='\033[0;36m'
NC='\033[0m'

printf "${CYAN}Let's go for a dRAGon ride! 🐉${NC}\n"
printf "\n"

printf "${YELLOW}[QUICKSTART]${NC}\n"
printf "\t${BLUE}✨ Launch full dRAGon app ${NC}\tgradle bootRun\n"
printf "\t${BLUE}Launch dRAGon backend only${NC}\tgradle bootRun -x :frontend:pnpmBuild -x :backend:copyWebApp\n"
printf "\t${BLUE}Launch dRAGon frontend only${NC}\tpnpm --prefix frontend dev\n"

printf "\n"
10 changes: 9 additions & 1 deletion .devcontainer/postCreate.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
#!/bin/bash

# Prepare PNPM
echo "Setting up pnpm store..."
mkdir -p /tmp/pnpm && pnpm config set store-dir /tmp/pnpm/

# Install dependencies
echo "Building the project..."
gradle pnpmInstall build
gradle pnpmInstall build

# Configure the message of the day
echo '/bin/sh .devcontainer/motd.sh' >> /home/vscode/.bashrc

# Let's go for a dRAGon ride! 🐉
printf "${GREEN}Let's go for a dRAGon ride! 🐉\n\n"
17 changes: 10 additions & 7 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ dependencies {
developmentOnly 'org.springframework.boot:spring-boot-devtools'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.6.0'

implementation 'dev.langchain4j:langchain4j:0.33.0'
implementation 'dev.langchain4j:langchain4j-core:0.33.0'
implementation 'dev.langchain4j:langchain4j-embeddings:0.33.0'
implementation 'dev.langchain4j:langchain4j-pgvector:0.33.0'
implementation 'dev.langchain4j:langchain4j-easy-rag:0.33.0'
implementation 'dev.langchain4j:langchain4j-open-ai:0.33.0'
implementation 'dev.langchain4j:langchain4j-mistral-ai:0.33.0'
implementation 'dev.langchain4j:langchain4j:0.35.0'
implementation 'dev.langchain4j:langchain4j-core:0.35.0'
implementation 'dev.langchain4j:langchain4j-embeddings:0.35.0'
implementation 'dev.langchain4j:langchain4j-pgvector:0.35.0'
implementation 'dev.langchain4j:langchain4j-easy-rag:0.35.0'
implementation 'dev.langchain4j:langchain4j-open-ai:0.35.0'
implementation 'dev.langchain4j:langchain4j-mistral-ai:0.35.0'

implementation 'org.aspectj:aspectjrt:1.9.22.1'
implementation 'org.aspectj:aspectjweaver:1.9.22.1'

implementation platform('org.dizitart:nitrite-bom:4.3.0')
implementation 'org.dizitart:nitrite'
Expand Down
2 changes: 2 additions & 0 deletions backend/src/main/java/ai/dragon/DragonApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@SpringBootApplication
@EnableAspectJAutoProxy
public class DragonApplication {
public static void main(String[] args) {
SpringApplication.run(DragonApplication.class, args);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package ai.dragon.aspect.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GenericApiExceptionHandling {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package ai.dragon.aspect.api;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.dizitart.no2.exceptions.UniqueConstraintException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ai.dragon.dto.api.FailureApiResponse;
import jakarta.servlet.http.HttpServletResponse;

@Aspect
@Component
public class GenericApiExceptionHandlingAspect {
@Autowired
private HttpServletResponse response;

@Around("@annotation(GenericApiExceptionHandling)")
public Object handleException(ProceedingJoinPoint pjp) throws Throwable {
try {
return pjp.proceed();
} catch (Exception ex) {
int httpStatusCode = 500;
if(ex instanceof UniqueConstraintException) {
httpStatusCode = 422;
}
response.setStatus(httpStatusCode);

return FailureApiResponse
.builder()
.msg(ex.getMessage())
.code(String.format("0%d", httpStatusCode))
.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.fasterxml.jackson.databind.JsonMappingException;

import ai.dragon.aspect.api.GenericApiExceptionHandling;
import ai.dragon.dto.api.DataTableApiResponse;
import ai.dragon.dto.api.GenericApiResponse;
import ai.dragon.dto.api.SuccessApiResponse;
Expand Down Expand Up @@ -94,21 +95,25 @@ public GenericApiResponse updateFarm(
.build();
}

@GenericApiExceptionHandling
@PutMapping("/{uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}")
@ApiResponse(responseCode = "200", description = "Farm has been successfully updated.")
@ApiResponse(responseCode = "404", description = "Farm not found.", content = @Content)
@Operation(summary = "Upsert a Farm", description = "Upsert one Farm entity in the database.")
public GenericApiResponse upsertFarm(
@PathVariable("uuid") @Parameter(description = "Identifier of the Farm", required = false) String uuid,
@RequestBody Map<String, Object> fields) throws Exception {
if (uuid == null || UUIDUtil.zeroUUIDString().equals(uuid)) {
fields.remove("uuid");
uuid = super.create(farmRepository).getUuid().toString();
}
return SuccessApiResponse
.builder()
.data(super.update(uuid, fields, farmRepository))
.build();
return farmRepository.queryTransaction(transactionRepository -> {
String farmUUID = uuid;
if (farmUUID == null || UUIDUtil.zeroUUIDString().equals(farmUUID)) {
fields.remove("uuid");
farmUUID = super.create(transactionRepository).getUuid().toString();
}
return SuccessApiResponse
.builder()
.data(super.update(farmUUID, fields, transactionRepository))
.build();
});
}

@DeleteMapping("/{uuid:[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ai.dragon.dto.api;

import ai.dragon.dto.api.backend.PagerTableApiData;
import ai.dragon.enumeration.ApiResponseCode;
import ai.dragon.repository.util.Pager;
import lombok.Builder;
import lombok.Data;
Expand All @@ -12,7 +13,7 @@ public class DataTableApiResponse implements GenericApiResponse {
private TableApiData data = null;

@Builder.Default
private String code = "0000";
private String code = ApiResponseCode.SUCCESS.toString();

@Builder.Default
private String msg = "OK";
Expand Down
18 changes: 18 additions & 0 deletions backend/src/main/java/ai/dragon/dto/api/DuplicatesApiResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ai.dragon.dto.api;

import ai.dragon.enumeration.ApiResponseCode;
import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class DuplicatesApiResponse implements GenericApiResponse {
@Builder.Default
private Object data = null;

@Builder.Default
private String code = ApiResponseCode.DUPLICATES.toString();

@Builder.Default
private String msg = "Unique Constraint Exception";
}
18 changes: 18 additions & 0 deletions backend/src/main/java/ai/dragon/dto/api/FailureApiResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ai.dragon.dto.api;

import ai.dragon.enumeration.ApiResponseCode;
import lombok.Builder;
import lombok.Data;

@Builder
@Data
public class FailureApiResponse implements GenericApiResponse {
@Builder.Default
private Object data = null;

@Builder.Default
private String code = ApiResponseCode.INTERNAL_SERVER_ERROR.toString();

@Builder.Default
private String msg = "Internal Server Error";
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ai.dragon.dto.api;

import ai.dragon.enumeration.ApiResponseCode;
import lombok.Builder;
import lombok.Data;

Expand All @@ -10,7 +11,7 @@ public class SuccessApiResponse implements GenericApiResponse {
private Object data = null;

@Builder.Default
private String code = "0000";
private String code = ApiResponseCode.SUCCESS.toString();

@Builder.Default
private String msg = "OK";
Expand Down
5 changes: 5 additions & 0 deletions backend/src/main/java/ai/dragon/entity/FarmEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import ai.dragon.enumeration.ChatMemoryStrategy;
import ai.dragon.enumeration.LanguageModelType;
import ai.dragon.enumeration.QueryRouterType;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
Expand Down Expand Up @@ -57,12 +58,16 @@ public class FarmEntity implements AbstractEntity {
@Schema(description = "Settings to be linked to the Farm's Retrieval Augmentor in the form of `key = value` pairs.")
private List<String> retrievalAugmentorSettings;

@Schema(description = "Query Router to be used by the RaaG. If not set, the 'Default' query router will be used.", example = "LanguageModel")
private QueryRouterType queryRouter;

public FarmEntity() {
this.uuid = UUID.randomUUID();
this.name = String.format("Farm %s", this.uuid.toString());
this.silos = new ArrayList<UUID>();
this.raagIdentifier = UUID.randomUUID().toString();
this.languageModel = LanguageModelType.OpenAiModel;
this.chatMemoryStrategy = ChatMemoryStrategy.MaxMessages;
this.queryRouter = QueryRouterType.DEFAULT;
}
}
3 changes: 3 additions & 0 deletions backend/src/main/java/ai/dragon/entity/SiloEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public class SiloEntity implements AbstractEntity {
@Schema(description = "Name of the Silo. Must be unique.")
private String name;

@Schema(description = "Description of the Silo. Used by the Language Query Router to choose the best Silo among Farm chain.")
private String description;

@NotNull
@Schema(description = "Type to be used for the Vector Store", example = "InMemoryEmbeddingStore")
private VectorStoreType vectorStore;
Expand Down
27 changes: 27 additions & 0 deletions backend/src/main/java/ai/dragon/enumeration/ApiResponseCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ai.dragon.enumeration;

public enum ApiResponseCode {
SUCCESS("0000"),
DUPLICATES("0422"),
INTERNAL_SERVER_ERROR("0500");

private String value;

ApiResponseCode(String value) {
this.value = value;
}

public static ApiResponseCode fromString(String text) {
for (ApiResponseCode b : ApiResponseCode.values()) {
if (b.value.equalsIgnoreCase(text)) {
return b;
}
}
return null;
}

@Override
public String toString() {
return value;
}
}
26 changes: 26 additions & 0 deletions backend/src/main/java/ai/dragon/enumeration/QueryRouterType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package ai.dragon.enumeration;

public enum QueryRouterType {
DEFAULT("Default"),
LANGUAGE_MODEL("LanguageModel");

private String value;

QueryRouterType(String value) {
this.value = value;
}

public static QueryRouterType fromString(String text) {
for (QueryRouterType b : QueryRouterType.values()) {
if (b.value.equalsIgnoreCase(text)) {
return b;
}
}
return null;
}

@Override
public String toString() {
return value;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package ai.dragon.properties.raag;

import dev.langchain4j.model.input.PromptTemplate;
import dev.langchain4j.rag.query.router.LanguageModelQueryRouter;
import dev.langchain4j.rag.query.router.LanguageModelQueryRouter.FallbackStrategy;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand All @@ -12,6 +15,8 @@
public class RetrievalAugmentorSettings {
public static final Integer DEFAULT_MAX_MESSAGES = 10;
public static final Integer DEFAULT_MAX_TOKENS = 3000;
public static final PromptTemplate DEFAULT_LANGUAGE_QUERY_ROUTER_PROMPT_TEMPLATE = LanguageModelQueryRouter.DEFAULT_PROMPT_TEMPLATE;
public static final FallbackStrategy DEFAULT_LANGUAGE_QUERY_ROUTER_FALLBACK_STRATEGY = FallbackStrategy.FAIL;

@Builder.Default
private Boolean rewriteQuery = false;
Expand All @@ -21,4 +26,10 @@ public class RetrievalAugmentorSettings {

@Builder.Default
private Integer historyMaxTokens = DEFAULT_MAX_TOKENS;

@Builder.Default
private PromptTemplate languageQueryRouterPromptTemplate = DEFAULT_LANGUAGE_QUERY_ROUTER_PROMPT_TEMPLATE;

@Builder.Default
private FallbackStrategy languageQueryRouterFallbackStrategy = DEFAULT_LANGUAGE_QUERY_ROUTER_FALLBACK_STRATEGY;
}
Loading

0 comments on commit b60d8b1

Please sign in to comment.