Skip to content

Commit

Permalink
Watch files configured in @SystemMessage or @Usermessage
Browse files Browse the repository at this point in the history
  • Loading branch information
geoand committed May 30, 2024
1 parent d2e7248 commit 90b8916
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import io.quarkus.deployment.annotations.Record;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
import io.quarkus.deployment.builditem.HotDeploymentWatchedFileBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem;
import io.quarkus.deployment.metrics.MetricsCapabilityBuildItem;
Expand Down Expand Up @@ -554,6 +555,22 @@ public void handleDeclarativeServices(AiServicesRecorder recorder,
}
}

@BuildStep
public void watchResourceFiles(CombinedIndexBuildItem indexBuildItem,
BuildProducer<HotDeploymentWatchedFileBuildItem> producer) {
IndexView index = indexBuildItem.getIndex();
List<AnnotationInstance> instances = new ArrayList<>();
instances.addAll(index.getAnnotations(LangChain4jDotNames.SYSTEM_MESSAGE));
instances.addAll(index.getAnnotations(LangChain4jDotNames.USER_MESSAGE));

for (AnnotationInstance instance : instances) {
AnnotationValue fromResource = instance.value("fromResource");
if (fromResource != null) {
producer.produce(new HotDeploymentWatchedFileBuildItem(fromResource.asString()));
}
}
}

@BuildStep
@Record(ExecutionTime.STATIC_INIT)
public void handleAiServices(AiServicesRecorder recorder,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkiverse.langchain4j.openai.test;

import static io.restassured.RestAssured.get;
import static org.assertj.core.api.Assertions.assertThat;

import java.util.function.Function;

Expand All @@ -10,24 +11,29 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import com.github.tomakehurst.wiremock.stubbing.ServeEvent;

import io.quarkiverse.langchain4j.testing.internal.WiremockAware;
import io.quarkus.test.QuarkusDevModeTest;

public class PromptDevModeTest {
public class PromptDevModeTest extends WiremockAware {

@RegisterExtension
static final QuarkusDevModeTest devModeTest = new QuarkusDevModeTest()
.setArchiveProducer(() -> ShrinkWrap.create(JavaArchive.class)
.addClasses(Service.class, Resource.class, Configuration.class, ConfigurationKey.class,
.addClasses(Service.class, ServiceWithResource.class, Resource.class, Configuration.class,
ConfigurationKey.class,
Resource.ApplicationGlobals.class)
.addAsResource(
new StringAsset(
String.format("quarkus.langchain4j.openai.base-url=%s",
String.format(
"quarkus.wiremock.devservices.reload=false\nquarkus.langchain4j.openai.base-url=%s",
WiremockAware.wiremockUrlForConfig("/v1"))),
"application.properties"));
"application.properties")
.addAsResource("cs-organizer.txt"));

@Test
public void test() {
public void testJavaChange() {
get("test")
.then()
.statusCode(200);
Expand All @@ -44,4 +50,38 @@ public String apply(String s) {
.statusCode(200);
}

@Test
public void testResourceChange() {
get("test/with-resource")
.then()
.statusCode(200);

// unfortunately the only way to get the port for a dev mode test is from the application
int wiremockPort = Integer.parseInt(get("test/wiremock")
.then()
.statusCode(200)
.extract()
.body()
.asString());

var requestBody = singleLoggedRequest(wiremock(wiremockPort)).getBody();
assertThat(new String(requestBody)).contains("science");

devModeTest.modifyResourceFile("cs-organizer.txt", new Function<String, String>() {
@Override
public String apply(String s) {
return s.replace("science", "programming");
}
});

get("test/with-resource")
.then()
.statusCode(200);

assertThat(wiremock(wiremockPort).getServeEvents()).hasSize(2);
ServeEvent serveEvent = wiremock().getServeEvents().get(0);
requestBody = serveEvent.getRequest().getBody();
assertThat(new String(requestBody)).contains("programming");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,42 @@
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.eclipse.microprofile.config.inject.ConfigProperty;

import io.quarkus.qute.TemplateGlobal;

@Path("/test")
public class Resource {

private final Service service;
private final ServiceWithResource serviceWithResource;
private final Integer wiremockPort;

public Resource(Service service) {
public Resource(Service service, ServiceWithResource serviceWithResource,
@ConfigProperty(name = "quarkus.wiremock.devservices.port") Integer wiremockPort) {
this.service = service;
this.serviceWithResource = serviceWithResource;
this.wiremockPort = wiremockPort;
}

@GET
public String hello() {
return service.findTalks("java");
}

@GET
@Path("with-resource")
public String withResource() {
return serviceWithResource.findTalks("java");
}

// needed because the dev mode test does not have access to this because of ClassLoaders
@GET
@Path("wiremock")
public Integer wiremockPort() {
return wiremockPort;
}

@TemplateGlobal
public static class ApplicationGlobals {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.quarkiverse.langchain4j.openai.test;

import dev.langchain4j.service.SystemMessage;
import dev.langchain4j.service.UserMessage;
import io.quarkiverse.langchain4j.RegisterAiService;

@RegisterAiService
public interface ServiceWithResource {

@SystemMessage(fromResource = "cs-organizer.txt")
@UserMessage("""
Help me select talks that match my favorite topics: {topics}. Give me the list of talks.
""")
String findTalks(String topics);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
You are a computer science conference organiser
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ protected WireMock wiremock() {
return wireMock;
}

protected WireMock wiremock(Integer port) {
if (wireMock == null) {
wireMock = new WireMock(port);
}
return wireMock;
}

protected Integer getResolvedWiremockPort() {
return ConfigProvider.getConfig().getValue("quarkus.wiremock.devservices.port", Integer.class);
}
Expand All @@ -74,7 +81,11 @@ protected void resetMappings() {
}

protected LoggedRequest singleLoggedRequest() {
assertThat(wiremock().getServeEvents()).hasSize(1);
return singleLoggedRequest(wiremock());
}

protected LoggedRequest singleLoggedRequest(WireMock wireMock) {
assertThat(wireMock.getServeEvents()).hasSize(1);
ServeEvent serveEvent = wiremock().getServeEvents().get(0);
return serveEvent.getRequest();
}
Expand Down

0 comments on commit 90b8916

Please sign in to comment.