Skip to content
Open
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ portal/src/main/webapp/WEB-INF/logback.xml
firehose-importer/reference_data/gene_info
portal.properties
src/main/resources/application.properties
microservices/assistant/src/main/resources/application.properties
importer.properties
log4j.properties
build.properties
Expand Down
19 changes: 19 additions & 0 deletions microservices/assistant/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM maven:3-eclipse-temurin-17 as build

WORKDIR /assistant

COPY pom.xml .

RUN mvn dependency:go-offline --fail-never

COPY src ./src

RUN mvn install package -DskipTests

FROM eclipse-temurin:17-jre-jammy

WORKDIR /assistant

COPY --from=build /assistant/target/assistant.jar .

ENTRYPOINT ["java","-jar","assistant.jar"]
257 changes: 257 additions & 0 deletions microservices/assistant/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.cbioportal.assistant</groupId>
<artifactId>assistant</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>gene-assistant</name>
<description>Gene Assistant Microservice</description>

<properties>
<java.version>17</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>3.2.5</spring-boot.version>
<jib-maven-plugin.version>3.4.2</jib-maven-plugin.version>
<spotless.version>2.43.0</spotless.version>
<jacoco.version>0.8.12</jacoco.version>
<maven-failsafe-plugin.version>3.2.5</maven-failsafe-plugin.version>
<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
<build-helper-maven-plugin.version>3.6.0</build-helper-maven-plugin.version>
<test.server.port>8080</test.server.port>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-azure-openai</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-azure-openai</artifactId>
<version>1.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.13.0</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<runOrder>random</runOrder>
<rerunFailingTestsCount>1</rerunFailingTestsCount>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>${jacoco.version}</version>
<executions>
<execution>
<id>default-prepare-agent</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>default-report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-failsafe-plugin.version}</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.diffplug.spotless</groupId>
<artifactId>spotless-maven-plugin</artifactId>
<version>${spotless.version}</version>
<configuration>
<java>
<googleJavaFormat>
<version>1.25.2</version>
<style>AOSP</style>
</googleJavaFormat>
</java>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${build-helper-maven-plugin.version}</version>
<executions>
<execution>
<id>reserve-network-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<portNames>
<portName>test.server.port</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>jib</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<build>
<plugins>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>${jib-maven-plugin.version}</version>
<configuration>
<from>
<image>eclipse-temurin:17-jre-jammy</image>
</from>
<to>
<image>ghcr.io/cbioportal/gene-assistant:${project.version}</image>
</to>
<container>
<ports>
<port>8080</port>
</ports>
</container>
</configuration>
<executions>
<execution>
<goals>
<goal>build</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>

<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
</repositories>

<distributionManagement>
<repository>
<id>github</id>
<name>GitHub Packages</name>
<url>https://maven.pkg.github.com/cbioportal/cbioportal</url>
</repository>
</distributionManagement>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.cbioportal.assistant;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
@ConditionalOnProperty(name = "spring.ai.enabled", havingValue = "true")
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

private final AssistantService assistantService;

@Autowired
public Application(AssistantService assistantService) {
this.assistantService = assistantService;
}

@Operation(description = "Send query to AI model for gene assistance")
@ApiResponse(
responseCode = "200",
description = "OK",
content = @Content(schema = @Schema(implementation = ChatResponse.class)))
@PostMapping(value = "/", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> fetchGeneAssistantResponse(@RequestBody String message) {
ChatResponse chatResponse = assistantService.generateResponse(message);
return ResponseEntity.ok(chatResponse.getResult().getOutput().getText().toString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package org.cbioportal.assistant;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;

@Service
public class AssistantService {

private static final String OQL_CONTEXT_FILE = "oql-context.st";
private final ChatModel chatModel;

@Autowired
public AssistantService(ChatModel chatModel) {
this.chatModel = chatModel;
}

public ChatResponse generateResponse(String message) {
try {
Resource oqlContextResource = new ClassPathResource(OQL_CONTEXT_FILE);
String oqlContext =
new String(
oqlContextResource.getInputStream().readAllBytes(),
StandardCharsets.UTF_8);
Message systemMessage = new SystemMessage(oqlContext);
Message userMessage = new UserMessage(message);

Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
ChatResponse response = this.chatModel.call(prompt);
return response;

} catch (IOException e) {
throw new UncheckedIOException("Failed to read oql context prompt resource", e);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
server.port=8090

# Spring AI Properties 1.0.3, see https://docs.spring.io/spring-ai/reference/api/chatmodel.html for other configurable models
spring.ai.enabled=true
spring.ai.azure.openai.api-key=
spring.ai.azure.openai.endpoint=
spring.ai.azure.openai.chat.options.deployment-name=
spring.ai.model.chat=
Empty file.
Loading
Loading