From b1c12e25e9698501440b46bca37ada23c5116239 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Tue, 25 Apr 2023 20:06:15 +0200 Subject: Put the openai client in a separate component --- cloud-tenant-base-dependencies-enforcer/pom.xml | 12 -- .../src/test/resources/exportPackages.properties | 4 +- model-integration/abi-spec.json | 161 ++------------ model-integration/pom.xml | 17 -- .../src/main/java/ai/vespa/llm/Completion.java | 41 ---- .../src/main/java/ai/vespa/llm/Generator.java | 232 --------------------- .../main/java/ai/vespa/llm/GeneratorOptions.java | 37 ---- .../src/main/java/ai/vespa/llm/LanguageModel.java | 18 -- .../src/main/java/ai/vespa/llm/Prompt.java | 23 -- .../src/main/java/ai/vespa/llm/StringPrompt.java | 43 ---- .../java/ai/vespa/llm/client/OpenAiClient.java | 84 -------- .../java/ai/vespa/llm/client/package-info.java | 11 - .../java/ai/vespa/llm/generation/Generator.java | 232 +++++++++++++++++++++ .../ai/vespa/llm/generation/GeneratorOptions.java | 37 ++++ .../java/ai/vespa/llm/generation/package-info.java | 11 + .../src/main/java/ai/vespa/llm/package-info.java | 11 - .../java/ai/vespa/llm/test/MockLanguageModel.java | 44 ---- .../main/java/ai/vespa/llm/test/package-info.java | 11 - .../src/test/java/ai/vespa/llm/CompletionTest.java | 37 ---- .../src/test/java/ai/vespa/llm/GeneratorTest.java | 40 ---- .../ai/vespa/llm/generation/GeneratorTest.java | 42 ++++ openai-client/abi-spec.json | 29 +++ openai-client/pom.xml | 67 ++++++ .../ai/vespa/llm/client/openai/OpenAiClient.java | 84 ++++++++ .../ai/vespa/llm/client/openai/package-info.java | 11 + parent/pom.xml | 12 -- pom.xml | 3 +- vespajlib/abi-spec.json | 108 ++++++++++ .../src/main/java/ai/vespa/llm/LanguageModel.java | 20 ++ .../java/ai/vespa/llm/completion/Completion.java | 41 ++++ .../main/java/ai/vespa/llm/completion/Prompt.java | 23 ++ .../java/ai/vespa/llm/completion/StringPrompt.java | 43 ++++ .../java/ai/vespa/llm/completion/package-info.java | 11 + .../src/main/java/ai/vespa/llm/package-info.java | 11 + .../java/ai/vespa/llm/test/MockLanguageModel.java | 44 ++++ .../main/java/ai/vespa/llm/test/package-info.java | 11 + .../ai/vespa/llm/completion/CompletionTest.java | 40 ++++ 37 files changed, 882 insertions(+), 824 deletions(-) delete mode 100644 model-integration/src/main/java/ai/vespa/llm/Completion.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/Generator.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/GeneratorOptions.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/LanguageModel.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/Prompt.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/StringPrompt.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/client/OpenAiClient.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/client/package-info.java create mode 100644 model-integration/src/main/java/ai/vespa/llm/generation/Generator.java create mode 100644 model-integration/src/main/java/ai/vespa/llm/generation/GeneratorOptions.java create mode 100644 model-integration/src/main/java/ai/vespa/llm/generation/package-info.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/package-info.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/test/MockLanguageModel.java delete mode 100644 model-integration/src/main/java/ai/vespa/llm/test/package-info.java delete mode 100644 model-integration/src/test/java/ai/vespa/llm/CompletionTest.java delete mode 100644 model-integration/src/test/java/ai/vespa/llm/GeneratorTest.java create mode 100644 model-integration/src/test/java/ai/vespa/llm/generation/GeneratorTest.java create mode 100644 openai-client/abi-spec.json create mode 100644 openai-client/pom.xml create mode 100644 openai-client/src/main/java/ai/vespa/llm/client/openai/OpenAiClient.java create mode 100644 openai-client/src/main/java/ai/vespa/llm/client/openai/package-info.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/LanguageModel.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/completion/Completion.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/completion/Prompt.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/completion/StringPrompt.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/completion/package-info.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/package-info.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/test/MockLanguageModel.java create mode 100644 vespajlib/src/main/java/ai/vespa/llm/test/package-info.java create mode 100644 vespajlib/src/test/java/ai/vespa/llm/completion/CompletionTest.java diff --git a/cloud-tenant-base-dependencies-enforcer/pom.xml b/cloud-tenant-base-dependencies-enforcer/pom.xml index 7971f4eebcf..1f179013b32 100644 --- a/cloud-tenant-base-dependencies-enforcer/pom.xml +++ b/cloud-tenant-base-dependencies-enforcer/pom.xml @@ -235,18 +235,6 @@ org.osgi:org.osgi.compendium:4.1.0:test org.osgi:org.osgi.core:4.1.0:test xerces:xercesImpl:2.12.2:test - - com.squareup.okhttp3:okhttp:3.14.9:test - com.squareup.okio:okio:1.17.2:test - com.squareup.retrofit2:adapter-rxjava2:2.9.0:test - com.squareup.retrofit2:converter-jackson:2.9.0:test - com.squareup.retrofit2:retrofit:2.9.0:test - com.theokanning.openai-gpt3-java:api:${openai-gpt3.version}:test - com.theokanning.openai-gpt3-java:client:${openai-gpt3.version}:test - com.theokanning.openai-gpt3-java:service:${openai-gpt3.version}:test - io.reactivex.rxjava2:rxjava:2.0.0:test - org.reactivestreams:reactive-streams:1.0.3:test - diff --git a/jdisc_core/src/test/resources/exportPackages.properties b/jdisc_core/src/test/resources/exportPackages.properties index b49f91842e3..8af15fe591d 100644 --- a/jdisc_core/src/test/resources/exportPackages.properties +++ b/jdisc_core/src/test/resources/exportPackages.properties @@ -1,3 +1,3 @@ #generated by com.yahoo.jdisc.core.ExportPackages -#Wed Jul 20 02:55:26 CEST 2022 -exportPackages=org.osgi.framework; version\="1.10.0", org.osgi.framework.connect; version\="1.0.0", org.osgi.framework.dto; uses\:\="org.osgi.dto"; version\="1.8.0", org.osgi.framework.hooks.bundle; uses\:\="org.osgi.framework"; version\="1.1.0", org.osgi.framework.hooks.resolver; uses\:\="org.osgi.framework.wiring"; version\="1.0.0", org.osgi.framework.hooks.service; uses\:\="org.osgi.framework"; version\="1.1.0", org.osgi.framework.hooks.weaving; uses\:\="org.osgi.framework.wiring"; version\="1.1.0", org.osgi.framework.launch; uses\:\="org.osgi.framework"; version\="1.2.0", org.osgi.framework.namespace; uses\:\="org.osgi.resource"; version\="1.2.0", org.osgi.framework.startlevel; uses\:\="org.osgi.framework"; version\="1.0.0", org.osgi.framework.startlevel.dto; uses\:\="org.osgi.dto"; version\="1.0.0", org.osgi.framework.wiring; uses\:\="org.osgi.framework,org.osgi.resource"; version\="1.2.0", org.osgi.framework.wiring.dto; uses\:\="org.osgi.dto,org.osgi.resource.dto"; version\="1.3.0", org.osgi.resource; version\="1.0.1", org.osgi.resource.dto; uses\:\="org.osgi.dto"; version\="1.0.1", org.osgi.service.packageadmin; uses\:\="org.osgi.framework"; version\="1.2.1", org.osgi.service.startlevel; uses\:\="org.osgi.framework"; version\="1.1.1", org.osgi.service.url; version\="1.0.1", org.osgi.service.resolver; uses\:\="org.osgi.resource"; version\="1.1.1", org.osgi.util.tracker; uses\:\="org.osgi.framework"; version\="1.5.3", org.osgi.dto; version\="1.1.1", org.osgi.service.condition; version\="1.0.0", javax.security.auth.callback; version\="0.0.0.JavaSE_017", javax.security.auth.login; version\="0.0.0.JavaSE_017", javax.net.ssl; version\="0.0.0.JavaSE_017", java.lang.constant; version\="0.0.0.JavaSE_017", java.security.interfaces; version\="0.0.0.JavaSE_017", java.text.spi; version\="0.0.0.JavaSE_017", java.nio.channels.spi; version\="0.0.0.JavaSE_017", java.math; version\="0.0.0.JavaSE_017", java.nio.file; version\="0.0.0.JavaSE_017", java.util.concurrent.atomic; version\="0.0.0.JavaSE_017", java.security.cert; version\="0.0.0.JavaSE_017", java.security.spec; version\="0.0.0.JavaSE_017", java.nio.channels; version\="0.0.0.JavaSE_017", java.time.chrono; version\="0.0.0.JavaSE_017", javax.crypto; version\="0.0.0.JavaSE_017", java.time.zone; version\="0.0.0.JavaSE_017", java.nio.charset; version\="0.0.0.JavaSE_017", java.io; version\="0.0.0.JavaSE_017", java.util.spi; version\="0.0.0.JavaSE_017", java.net; version\="0.0.0.JavaSE_017", javax.security.cert; version\="0.0.0.JavaSE_017", java.lang.annotation; version\="0.0.0.JavaSE_017", javax.security.auth.spi; version\="0.0.0.JavaSE_017", java.util.concurrent; version\="0.0.0.JavaSE_017", java.nio.charset.spi; version\="0.0.0.JavaSE_017", javax.crypto.interfaces; version\="0.0.0.JavaSE_017", java.util; version\="0.0.0.JavaSE_017", java.security; version\="0.0.0.JavaSE_017", java.nio.file.spi; version\="0.0.0.JavaSE_017", java.nio; version\="0.0.0.JavaSE_017", java.util.jar; version\="0.0.0.JavaSE_017", javax.security.auth; version\="0.0.0.JavaSE_017", java.lang.ref; version\="0.0.0.JavaSE_017", java.util.regex; version\="0.0.0.JavaSE_017", java.net.spi; version\="0.0.0.JavaSE_017", java.lang.module; version\="0.0.0.JavaSE_017", java.lang.invoke; version\="0.0.0.JavaSE_017", java.time.format; version\="0.0.0.JavaSE_017", java.util.concurrent.locks; version\="0.0.0.JavaSE_017", java.time.temporal; version\="0.0.0.JavaSE_017", java.util.zip; version\="0.0.0.JavaSE_017", java.nio.file.attribute; version\="0.0.0.JavaSE_017", java.util.random; version\="0.0.0.JavaSE_017", java.text; version\="0.0.0.JavaSE_017", javax.crypto.spec; version\="0.0.0.JavaSE_017", java.util.stream; version\="0.0.0.JavaSE_017", java.time; version\="0.0.0.JavaSE_017", java.lang; version\="0.0.0.JavaSE_017", java.lang.runtime; version\="0.0.0.JavaSE_017", java.util.function; version\="0.0.0.JavaSE_017", javax.net; version\="0.0.0.JavaSE_017", javax.security.auth.x500; version\="0.0.0.JavaSE_017", java.lang.reflect; version\="0.0.0.JavaSE_017", javax.lang.model; version\="0.0.0.JavaSE_017", javax.annotation.processing; version\="0.0.0.JavaSE_017", javax.lang.model.element; version\="0.0.0.JavaSE_017", javax.tools; version\="0.0.0.JavaSE_017", javax.lang.model.type; version\="0.0.0.JavaSE_017", javax.lang.model.util; version\="0.0.0.JavaSE_017", java.awt.datatransfer; version\="0.0.0.JavaSE_017", java.awt.desktop; version\="0.0.0.JavaSE_017", javax.swing.plaf.synth; version\="0.0.0.JavaSE_017", java.beans; version\="0.0.0.JavaSE_017", javax.swing.text.html.parser; version\="0.0.0.JavaSE_017", javax.swing.text.rtf; version\="0.0.0.JavaSE_017", java.awt.font; version\="0.0.0.JavaSE_017", javax.imageio; version\="0.0.0.JavaSE_017", java.awt.im.spi; version\="0.0.0.JavaSE_017", java.applet; version\="0.0.0.JavaSE_017", javax.sound.midi; version\="0.0.0.JavaSE_017", java.awt.dnd; version\="0.0.0.JavaSE_017", javax.swing.text; version\="0.0.0.JavaSE_017", javax.swing.plaf.basic; version\="0.0.0.JavaSE_017", javax.swing.undo; version\="0.0.0.JavaSE_017", javax.swing.plaf; version\="0.0.0.JavaSE_017", javax.swing.filechooser; version\="0.0.0.JavaSE_017", javax.imageio.event; version\="0.0.0.JavaSE_017", javax.sound.sampled; version\="0.0.0.JavaSE_017", javax.print.attribute; version\="0.0.0.JavaSE_017", javax.print; version\="0.0.0.JavaSE_017", javax.swing.plaf.nimbus; version\="0.0.0.JavaSE_017", javax.accessibility; version\="0.0.0.JavaSE_017", java.awt.event; version\="0.0.0.JavaSE_017", javax.swing.text.html; version\="0.0.0.JavaSE_017", javax.imageio.spi; version\="0.0.0.JavaSE_017", javax.swing.border; version\="0.0.0.JavaSE_017", javax.sound.sampled.spi; version\="0.0.0.JavaSE_017", javax.imageio.plugins.bmp; version\="0.0.0.JavaSE_017", java.awt.color; version\="0.0.0.JavaSE_017", java.awt.geom; version\="0.0.0.JavaSE_017", javax.imageio.plugins.jpeg; version\="0.0.0.JavaSE_017", javax.swing.tree; version\="0.0.0.JavaSE_017", javax.imageio.plugins.tiff; version\="0.0.0.JavaSE_017", java.awt.print; version\="0.0.0.JavaSE_017", java.awt.image; version\="0.0.0.JavaSE_017", javax.imageio.metadata; version\="0.0.0.JavaSE_017", javax.swing.table; version\="0.0.0.JavaSE_017", javax.sound.midi.spi; version\="0.0.0.JavaSE_017", javax.print.attribute.standard; version\="0.0.0.JavaSE_017", javax.swing.colorchooser; version\="0.0.0.JavaSE_017", javax.swing; version\="0.0.0.JavaSE_017", java.awt.image.renderable; version\="0.0.0.JavaSE_017", javax.swing.plaf.multi; version\="0.0.0.JavaSE_017", java.awt.im; version\="0.0.0.JavaSE_017", javax.print.event; version\="0.0.0.JavaSE_017", javax.swing.plaf.metal; version\="0.0.0.JavaSE_017", java.beans.beancontext; version\="0.0.0.JavaSE_017", java.awt; version\="0.0.0.JavaSE_017", javax.imageio.stream; version\="0.0.0.JavaSE_017", javax.swing.event; version\="0.0.0.JavaSE_017", java.lang.instrument; version\="0.0.0.JavaSE_017", java.util.logging; version\="0.0.0.JavaSE_017", javax.management.timer; version\="0.0.0.JavaSE_017", javax.management; version\="0.0.0.JavaSE_017", javax.management.relation; version\="0.0.0.JavaSE_017", javax.management.loading; version\="0.0.0.JavaSE_017", javax.management.openmbean; version\="0.0.0.JavaSE_017", java.lang.management; version\="0.0.0.JavaSE_017", javax.management.remote; version\="0.0.0.JavaSE_017", javax.management.monitor; version\="0.0.0.JavaSE_017", javax.management.modelmbean; version\="0.0.0.JavaSE_017", javax.management.remote.rmi; version\="0.0.0.JavaSE_017", javax.naming.event; version\="0.0.0.JavaSE_017", javax.naming.ldap.spi; version\="0.0.0.JavaSE_017", javax.naming; version\="0.0.0.JavaSE_017", javax.naming.spi; version\="0.0.0.JavaSE_017", javax.naming.ldap; version\="0.0.0.JavaSE_017", javax.naming.directory; version\="0.0.0.JavaSE_017", java.net.http; version\="0.0.0.JavaSE_017", java.util.prefs; version\="0.0.0.JavaSE_017", java.rmi.registry; version\="0.0.0.JavaSE_017", javax.rmi.ssl; version\="0.0.0.JavaSE_017", java.rmi.dgc; version\="0.0.0.JavaSE_017", java.rmi; version\="0.0.0.JavaSE_017", java.rmi.server; version\="0.0.0.JavaSE_017", javax.script; version\="0.0.0.JavaSE_017", org.ietf.jgss; version\="0.0.0.JavaSE_017", javax.security.auth.kerberos; version\="0.0.0.JavaSE_017", javax.security.sasl; version\="0.0.0.JavaSE_017", javax.smartcardio; version\="0.0.0.JavaSE_017", java.sql; version\="0.0.0.JavaSE_017", javax.sql; version\="0.0.0.JavaSE_017", javax.sql.rowset.spi; version\="0.0.0.JavaSE_017", javax.sql.rowset.serial; version\="0.0.0.JavaSE_017", javax.sql.rowset; version\="0.0.0.JavaSE_017", javax.transaction.xa; version\="0.0.0.JavaSE_017", javax.xml; version\="0.0.0.JavaSE_017", javax.xml.transform.sax; version\="0.0.0.JavaSE_017", javax.xml.datatype; version\="0.0.0.JavaSE_017", javax.xml.catalog; version\="0.0.0.JavaSE_017", org.w3c.dom.traversal; version\="0.0.0.JavaSE_017", javax.xml.stream.events; version\="0.0.0.JavaSE_017", javax.xml.stream; version\="0.0.0.JavaSE_017", org.xml.sax; version\="0.0.0.JavaSE_017", javax.xml.transform; version\="0.0.0.JavaSE_017", javax.xml.xpath; version\="0.0.0.JavaSE_017", org.w3c.dom.events; version\="0.0.0.JavaSE_017", org.w3c.dom.ranges; version\="0.0.0.JavaSE_017", org.w3c.dom.ls; version\="0.0.0.JavaSE_017", javax.xml.stream.util; version\="0.0.0.JavaSE_017", javax.xml.namespace; version\="0.0.0.JavaSE_017", javax.xml.transform.stax; version\="0.0.0.JavaSE_017", org.xml.sax.helpers; version\="0.0.0.JavaSE_017", org.w3c.dom.views; version\="0.0.0.JavaSE_017", org.w3c.dom.bootstrap; version\="0.0.0.JavaSE_017", org.w3c.dom; version\="0.0.0.JavaSE_017", javax.xml.transform.stream; version\="0.0.0.JavaSE_017", javax.xml.transform.dom; version\="0.0.0.JavaSE_017", javax.xml.validation; version\="0.0.0.JavaSE_017", javax.xml.parsers; version\="0.0.0.JavaSE_017", org.xml.sax.ext; version\="0.0.0.JavaSE_017", javax.xml.crypto.dsig.spec; version\="0.0.0.JavaSE_017", javax.xml.crypto.dsig.keyinfo; version\="0.0.0.JavaSE_017", javax.xml.crypto.dsig.dom; version\="0.0.0.JavaSE_017", javax.xml.crypto.dom; version\="0.0.0.JavaSE_017", javax.xml.crypto; version\="0.0.0.JavaSE_017", javax.xml.crypto.dsig; version\="0.0.0.JavaSE_017", com.sun.java.accessibility.util; version\="0.0.0.JavaSE_017", com.sun.tools.attach.spi; version\="0.0.0.JavaSE_017", com.sun.tools.attach; version\="0.0.0.JavaSE_017", com.sun.source.doctree; version\="0.0.0.JavaSE_017", com.sun.source.tree; version\="0.0.0.JavaSE_017", com.sun.source.util; version\="0.0.0.JavaSE_017", com.sun.tools.javac; version\="0.0.0.JavaSE_017", jdk.dynalink.beans; version\="0.0.0.JavaSE_017", jdk.dynalink.linker.support; version\="0.0.0.JavaSE_017", jdk.dynalink.support; version\="0.0.0.JavaSE_017", jdk.dynalink; version\="0.0.0.JavaSE_017", jdk.dynalink.linker; version\="0.0.0.JavaSE_017", com.sun.net.httpserver; version\="0.0.0.JavaSE_017", com.sun.net.httpserver.spi; version\="0.0.0.JavaSE_017", com.sun.jarsigner; version\="0.0.0.JavaSE_017", jdk.security.jarsigner; version\="0.0.0.JavaSE_017", jdk.javadoc.doclet; version\="0.0.0.JavaSE_017", com.sun.tools.jconsole; version\="0.0.0.JavaSE_017", com.sun.jdi.connect; version\="0.0.0.JavaSE_017", com.sun.jdi.event; version\="0.0.0.JavaSE_017", com.sun.jdi.connect.spi; version\="0.0.0.JavaSE_017", com.sun.jdi; version\="0.0.0.JavaSE_017", com.sun.jdi.request; version\="0.0.0.JavaSE_017", jdk.jfr.consumer; version\="0.0.0.JavaSE_017", jdk.jfr; version\="0.0.0.JavaSE_017", jdk.jshell; version\="0.0.0.JavaSE_017", jdk.jshell.execution; version\="0.0.0.JavaSE_017", jdk.jshell.spi; version\="0.0.0.JavaSE_017", jdk.jshell.tool; version\="0.0.0.JavaSE_017", netscape.javascript; version\="0.0.0.JavaSE_017", com.sun.management; version\="0.0.0.JavaSE_017", jdk.management.jfr; version\="0.0.0.JavaSE_017", jdk.net; version\="0.0.0.JavaSE_017", jdk.nio; version\="0.0.0.JavaSE_017", jdk.nio.mapmode; version\="0.0.0.JavaSE_017", com.sun.nio.sctp; version\="0.0.0.JavaSE_017", com.sun.security.auth.module; version\="0.0.0.JavaSE_017", com.sun.security.auth.login; version\="0.0.0.JavaSE_017", com.sun.security.auth; version\="0.0.0.JavaSE_017", com.sun.security.auth.callback; version\="0.0.0.JavaSE_017", com.sun.security.jgss; version\="0.0.0.JavaSE_017", sun.reflect; version\="0.0.0.JavaSE_017", sun.misc; version\="0.0.0.JavaSE_017", com.sun.nio.file; version\="0.0.0.JavaSE_017", jdk.swing.interop; version\="0.0.0.JavaSE_017", org.w3c.dom.stylesheets; version\="0.0.0.JavaSE_017", org.w3c.dom.html; version\="0.0.0.JavaSE_017", org.w3c.dom.xpath; version\="0.0.0.JavaSE_017", org.w3c.dom.css; version\="0.0.0.JavaSE_017", com.yahoo.jdisc, com.yahoo.jdisc.application, com.yahoo.jdisc.handler, com.yahoo.jdisc.service, com.yahoo.jdisc.statistics, com.yahoo.jdisc.refcount, javax.inject;version\=1.0.0, org.aopalliance.intercept, org.aopalliance.aop, com.google.common.annotations;version\="27.1.0",com.google.common.base;version\="27.1.0",com.google.common.cache;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.util.concurrent",com.google.common.collect;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.escape;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.eventbus;version\="27.1.0",com.google.common.graph;version\="27.1.0";uses\:\="com.google.common.collect",com.google.common.hash;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.html;version\="27.1.0";uses\:\="com.google.common.escape",com.google.common.io;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.graph,com.google.common.hash",com.google.common.math;version\="27.1.0",com.google.common.net;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.escape",com.google.common.primitives;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.reflect;version\="27.1.0";uses\:\="com.google.common.collect,com.google.common.io",com.google.common.util.concurrent;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.util.concurrent.internal",com.google.common.xml;version\="27.1.0";uses\:\="com.google.common.escape", com.google.inject;version\="1.4",com.google.inject.binder;version\="1.4",com.google.inject.matcher;version\="1.4",com.google.inject.multibindings;version\="1.4",com.google.inject.name;version\="1.4",com.google.inject.spi;version\="1.4",com.google.inject.util;version\="1.4", org.slf4j;version\=1.7.32, org.slf4j.spi;version\=1.7.32, org.slf4j.helpers;version\=1.7.32, org.slf4j.event;version\=1.7.32, org.slf4j.impl;version\=1.7.32, org.apache.commons.logging;version\=1.2, org.apache.commons.logging.impl;version\=1.2, org.apache.log4j;version\=1.2.17,org.apache.log4j.helpers;version\=1.2.17,org.apache.log4j.spi;version\=1.2.17,org.apache.log4j.xml;version\=1.2.17, com.yahoo.component.annotation;version\="1.0.0", com.yahoo.config;version\=1.0.0, com.yahoo.vespa.defaults;version\=1.0.0, ai.vespa.http;version\=1.0.0,ai.vespa.validation;version\=1.0.0,com.yahoo.binaryprefix;version\=1.0.0,com.yahoo.collections;version\=1.0.0,com.yahoo.compress;version\=1.0.0,com.yahoo.concurrent.classlock;version\=1.0.0,com.yahoo.concurrent.maintenance;version\=1.0.0,com.yahoo.concurrent;version\=1.0.0,com.yahoo.data.access.simple;version\=1.0.0,com.yahoo.data.access.slime;version\=1.0.0,com.yahoo.data.access;version\=1.0.0,com.yahoo.errorhandling;version\=1.0.0,com.yahoo.exception;version\=1.0.0,com.yahoo.geo;version\=1.0.0,com.yahoo.io.reader;version\=1.0.0,com.yahoo.io;version\=1.0.0,com.yahoo.javacc;version\=1.0.0,com.yahoo.lang;version\=1.0.0,com.yahoo.nativec;version\=1.0.0,com.yahoo.net;version\=1.0.0,com.yahoo.path;version\=1.0.0,com.yahoo.protect;version\=1.0.0,com.yahoo.reflection;version\=1.0.0,com.yahoo.slime;version\=1.0.0,com.yahoo.stream;version\=1.0.0,com.yahoo.system.execution;version\=1.0.0,com.yahoo.system;version\=1.0.0,com.yahoo.tensor.evaluation;version\=1.0.0,com.yahoo.tensor.functions;version\=1.0.0,com.yahoo.tensor.serialization;version\=1.0.0,com.yahoo.tensor;version\=1.0.0,com.yahoo.text.internal;version\=1.0.0,com.yahoo.text;version\=1.0.0,com.yahoo.time;version\=1.0.0,com.yahoo.transaction;version\=1.0.0,com.yahoo.vespa.objects;version\=1.0.0,com.yahoo.yolean.chain;version\=1.0.0,com.yahoo.yolean.concurrent;version\=1.0.0,com.yahoo.yolean.function;version\=1.0.0,com.yahoo.yolean.system;version\=1.0.0,com.yahoo.yolean.trace;version\=1.0.0,com.yahoo.yolean;version\=1.0.0, com.yahoo.log.event;version\=1.0.0,com.yahoo.log.impl;version\=1.0.0,com.yahoo.log;version\=1.0.0, javax.xml.bind;version\="2.3";uses\:\="javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.validation,org.w3c.dom,org.xml.sax",javax.xml.bind.annotation;version\="2.3";uses\:\="javax.xml.bind,javax.xml.parsers,javax.xml.transform,javax.xml.transform.dom,org.w3c.dom",javax.xml.bind.annotation.adapters;version\="2.3",javax.xml.bind.attachment;version\="2.3";uses\:\="javax.activation",javax.xml.bind.helpers;version\="2.3";uses\:\="javax.xml.bind,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.stream,javax.xml.transform,javax.xml.validation,org.w3c.dom,org.xml.sax",javax.xml.bind.util;version\="2.3";uses\:\="javax.xml.bind,javax.xml.transform.sax", com.sun.istack;version\="3.0.5";uses\:\="javax.activation,javax.xml.stream,org.xml.sax,org.xml.sax.helpers",com.sun.istack.localization;version\="3.0.5",com.sun.istack.logging;version\="3.0.5",com.sun.xml.bind;uses\:\="org.xml.sax";version\="2.3.0",com.sun.xml.bind.annotation;version\="2.3.0",com.sun.xml.bind.api;uses\:\="org.xml.sax";version\="2.3.0",com.sun.xml.bind.api.impl;version\="2.3.0",com.sun.xml.bind.marshaller;uses\:\="javax.xml.parsers,org.w3c.dom,org.xml.sax,org.xml.sax.helpers";version\="2.3.0",com.sun.xml.bind.unmarshaller;uses\:\="com.sun.xml.bind.v2.runtime.unmarshaller,javax.xml.bind,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.util;version\="2.3.0",com.sun.xml.bind.v2;version\="2.3.0",com.sun.xml.bind.v2.model.annotation;uses\:\="com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.runtime";version\="2.3.0",com.sun.xml.bind.v2.model.core;uses\:\="com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.impl,com.sun.xml.bind.v2.model.nav,com.sun.xml.bind.v2.runtime,javax.activation,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.namespace,javax.xml.transform";version\="2.3.0",com.sun.xml.bind.v2.model.impl;uses\:\="com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.nav";version\="2.3.0",com.sun.xml.bind.v2.model.nav;uses\:\="com.sun.xml.bind.v2.runtime";version\="2.3.0",com.sun.xml.bind.v2.model.util;uses\:\="javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.runtime;uses\:\="com.sun.xml.bind.v2.model.annotation,javax.activation,javax.xml.bind,javax.xml.bind.annotation.adapters";version\="2.3.0",com.sun.xml.bind.v2.runtime.unmarshaller;uses\:\="javax.xml.bind,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.schemagen.episode;uses\:\="com.sun.xml.txw2,com.sun.xml.txw2.annotation";version\="2.3.0",com.sun.xml.bind.v2.util;uses\:\="javax.xml.parsers,javax.xml.transform,javax.xml.validation,javax.xml.xpath";version\="2.3.0",com.sun.xml.txw2;uses\:\="com.sun.xml.txw2.output,javax.xml.namespace";version\="2.3.0",com.sun.xml.txw2.annotation;version\="2.3.0",com.sun.xml.txw2.output;uses\:\="com.sun.xml.txw2,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stream,org.w3c.dom,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers";version\="2.3.0", com.sun.xml.bind;uses\:\="com.sun.xml.bind.v2.runtime.reflect,javax.xml.bind,javax.xml.bind.annotation.adapters,javax.xml.datatype,javax.xml.namespace,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.api;uses\:\="com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,javax.xml.bind,javax.xml.bind.attachment,javax.xml.namespace,javax.xml.stream,javax.xml.transform,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.marshaller;version\="2.3.0",com.sun.xml.bind.unmarshaller;uses\:\="org.xml.sax";version\="2.3.0",com.sun.xml.bind.util;uses\:\="com.sun.xml.bind,javax.xml.bind.helpers,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.annotation,javax.xml.bind";version\="2.3.0",com.sun.xml.bind.v2.bytecode;version\="2.3.0",com.sun.xml.bind.v2.model.annotation;uses\:\="com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.nav,com.sun.xml.bind.v2.runtime";version\="2.3.0",com.sun.xml.bind.v2.model.impl;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.nav,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,javax.activation,javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.model.runtime;uses\:\="com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.reflect,javax.xml.bind,javax.xml.namespace,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime;uses\:\="com.sun.istack,com.sun.xml.bind.api,com.sun.xml.bind.marshaller,com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime.output,com.sun.xml.bind.v2.runtime.property,com.sun.xml.bind.v2.runtime.unmarshaller,javax.activation,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.transform.sax,javax.xml.validation,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.output;uses\:\="com.sun.xml.bind.marshaller,com.sun.xml.bind.v2.runtime,com.sun.xml.fastinfoset.stax,javax.xml.stream,org.jvnet.staxex,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.property;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.reflect,com.sun.xml.bind.v2.runtime.unmarshaller,com.sun.xml.bind.v2.util,javax.xml.namespace,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.reflect;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.unmarshaller,javax.xml.bind,javax.xml.bind.annotation.adapters,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.reflect.opt;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.reflect,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.unmarshaller;uses\:\="com.sun.xml.bind,com.sun.xml.bind.api,com.sun.xml.bind.unmarshaller,com.sun.xml.bind.util,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.output,com.sun.xml.bind.v2.runtime.reflect,javax.activation,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.transform.sax,javax.xml.validation,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.schemagen;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.nav,com.sun.xml.txw2.output,javax.xml.bind,javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.schemagen.xmlschema;uses\:\="com.sun.xml.txw2,com.sun.xml.txw2.annotation,javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.util;uses\:\="com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.unmarshaller,javax.activation,javax.xml.namespace,javax.xml.transform.stream,org.xml.sax";version\="2.3.0", javax.activation;uses\:\="com.sun.activation.registries";version\="1.2",com.sun.activation.viewers;uses\:\="javax.activation";version\="1.2.0",com.sun.activation.registries;version\="1.2.0" +#Tue Apr 25 14:00:54 CEST 2023 +exportPackages=org.osgi.framework; version\="1.10.0", org.osgi.framework.connect; version\="1.0.0", org.osgi.framework.dto; uses\:\="org.osgi.dto"; version\="1.8.0", org.osgi.framework.hooks.bundle; uses\:\="org.osgi.framework"; version\="1.1.0", org.osgi.framework.hooks.resolver; uses\:\="org.osgi.framework.wiring"; version\="1.0.0", org.osgi.framework.hooks.service; uses\:\="org.osgi.framework"; version\="1.1.0", org.osgi.framework.hooks.weaving; uses\:\="org.osgi.framework.wiring"; version\="1.1.0", org.osgi.framework.launch; uses\:\="org.osgi.framework"; version\="1.2.0", org.osgi.framework.namespace; uses\:\="org.osgi.resource"; version\="1.2.0", org.osgi.framework.startlevel; uses\:\="org.osgi.framework"; version\="1.0.0", org.osgi.framework.startlevel.dto; uses\:\="org.osgi.dto"; version\="1.0.0", org.osgi.framework.wiring; uses\:\="org.osgi.framework,org.osgi.resource"; version\="1.2.0", org.osgi.framework.wiring.dto; uses\:\="org.osgi.dto,org.osgi.resource.dto"; version\="1.3.0", org.osgi.resource; version\="1.0.1", org.osgi.resource.dto; uses\:\="org.osgi.dto"; version\="1.0.1", org.osgi.service.packageadmin; uses\:\="org.osgi.framework"; version\="1.2.1", org.osgi.service.startlevel; uses\:\="org.osgi.framework"; version\="1.1.1", org.osgi.service.url; version\="1.0.1", org.osgi.service.resolver; uses\:\="org.osgi.resource"; version\="1.1.1", org.osgi.util.tracker; uses\:\="org.osgi.framework"; version\="1.5.3", org.osgi.dto; version\="1.1.1", org.osgi.service.condition; version\="1.0.0", javax.crypto.interfaces; version\="0.0.0.JavaSE_020", java.util; version\="0.0.0.JavaSE_020", java.security; version\="0.0.0.JavaSE_020", java.nio.file.spi; version\="0.0.0.JavaSE_020", java.nio; version\="0.0.0.JavaSE_020", java.util.jar; version\="0.0.0.JavaSE_020", javax.security.auth; version\="0.0.0.JavaSE_020", java.lang.ref; version\="0.0.0.JavaSE_020", java.util.regex; version\="0.0.0.JavaSE_020", java.net.spi; version\="0.0.0.JavaSE_020", java.lang.module; version\="0.0.0.JavaSE_020", java.lang.invoke; version\="0.0.0.JavaSE_020", java.time.format; version\="0.0.0.JavaSE_020", java.util.concurrent.locks; version\="0.0.0.JavaSE_020", java.time.temporal; version\="0.0.0.JavaSE_020", java.util.zip; version\="0.0.0.JavaSE_020", java.nio.file.attribute; version\="0.0.0.JavaSE_020", java.util.random; version\="0.0.0.JavaSE_020", java.text; version\="0.0.0.JavaSE_020", javax.crypto.spec; version\="0.0.0.JavaSE_020", java.util.stream; version\="0.0.0.JavaSE_020", java.time; version\="0.0.0.JavaSE_020", java.lang; version\="0.0.0.JavaSE_020", java.lang.runtime; version\="0.0.0.JavaSE_020", java.util.function; version\="0.0.0.JavaSE_020", javax.net; version\="0.0.0.JavaSE_020", javax.security.auth.x500; version\="0.0.0.JavaSE_020", java.lang.reflect; version\="0.0.0.JavaSE_020", javax.security.auth.callback; version\="0.0.0.JavaSE_020", javax.security.auth.login; version\="0.0.0.JavaSE_020", javax.net.ssl; version\="0.0.0.JavaSE_020", java.lang.constant; version\="0.0.0.JavaSE_020", java.security.interfaces; version\="0.0.0.JavaSE_020", java.text.spi; version\="0.0.0.JavaSE_020", java.nio.channels.spi; version\="0.0.0.JavaSE_020", java.math; version\="0.0.0.JavaSE_020", java.nio.file; version\="0.0.0.JavaSE_020", java.util.concurrent.atomic; version\="0.0.0.JavaSE_020", java.security.cert; version\="0.0.0.JavaSE_020", java.security.spec; version\="0.0.0.JavaSE_020", java.nio.channels; version\="0.0.0.JavaSE_020", java.time.chrono; version\="0.0.0.JavaSE_020", javax.crypto; version\="0.0.0.JavaSE_020", java.time.zone; version\="0.0.0.JavaSE_020", java.nio.charset; version\="0.0.0.JavaSE_020", java.lang.foreign; version\="0.0.0.JavaSE_020", java.io; version\="0.0.0.JavaSE_020", java.util.spi; version\="0.0.0.JavaSE_020", java.net; version\="0.0.0.JavaSE_020", javax.security.cert; version\="0.0.0.JavaSE_020", java.lang.annotation; version\="0.0.0.JavaSE_020", javax.security.auth.spi; version\="0.0.0.JavaSE_020", java.util.concurrent; version\="0.0.0.JavaSE_020", java.nio.charset.spi; version\="0.0.0.JavaSE_020", javax.tools; version\="0.0.0.JavaSE_020", javax.lang.model.type; version\="0.0.0.JavaSE_020", javax.lang.model.util; version\="0.0.0.JavaSE_020", javax.lang.model; version\="0.0.0.JavaSE_020", javax.annotation.processing; version\="0.0.0.JavaSE_020", javax.lang.model.element; version\="0.0.0.JavaSE_020", java.awt.datatransfer; version\="0.0.0.JavaSE_020", javax.accessibility; version\="0.0.0.JavaSE_020", java.awt.event; version\="0.0.0.JavaSE_020", javax.swing.text.html; version\="0.0.0.JavaSE_020", javax.imageio.spi; version\="0.0.0.JavaSE_020", javax.swing.border; version\="0.0.0.JavaSE_020", javax.sound.sampled.spi; version\="0.0.0.JavaSE_020", javax.imageio.plugins.bmp; version\="0.0.0.JavaSE_020", java.awt.color; version\="0.0.0.JavaSE_020", java.awt.geom; version\="0.0.0.JavaSE_020", javax.imageio.plugins.jpeg; version\="0.0.0.JavaSE_020", javax.swing.tree; version\="0.0.0.JavaSE_020", javax.imageio.plugins.tiff; version\="0.0.0.JavaSE_020", java.awt.print; version\="0.0.0.JavaSE_020", java.awt.image; version\="0.0.0.JavaSE_020", javax.imageio.metadata; version\="0.0.0.JavaSE_020", javax.swing.table; version\="0.0.0.JavaSE_020", javax.sound.midi.spi; version\="0.0.0.JavaSE_020", javax.print.attribute.standard; version\="0.0.0.JavaSE_020", javax.swing.colorchooser; version\="0.0.0.JavaSE_020", javax.swing; version\="0.0.0.JavaSE_020", java.awt.image.renderable; version\="0.0.0.JavaSE_020", javax.swing.plaf.multi; version\="0.0.0.JavaSE_020", java.awt.im; version\="0.0.0.JavaSE_020", javax.print.event; version\="0.0.0.JavaSE_020", javax.swing.plaf.metal; version\="0.0.0.JavaSE_020", java.beans.beancontext; version\="0.0.0.JavaSE_020", java.awt; version\="0.0.0.JavaSE_020", javax.imageio.stream; version\="0.0.0.JavaSE_020", javax.swing.event; version\="0.0.0.JavaSE_020", java.awt.desktop; version\="0.0.0.JavaSE_020", javax.swing.plaf.synth; version\="0.0.0.JavaSE_020", java.beans; version\="0.0.0.JavaSE_020", javax.swing.text.html.parser; version\="0.0.0.JavaSE_020", javax.swing.text.rtf; version\="0.0.0.JavaSE_020", java.awt.font; version\="0.0.0.JavaSE_020", javax.imageio; version\="0.0.0.JavaSE_020", java.awt.im.spi; version\="0.0.0.JavaSE_020", java.applet; version\="0.0.0.JavaSE_020", javax.sound.midi; version\="0.0.0.JavaSE_020", java.awt.dnd; version\="0.0.0.JavaSE_020", javax.swing.text; version\="0.0.0.JavaSE_020", javax.swing.plaf.basic; version\="0.0.0.JavaSE_020", javax.swing.undo; version\="0.0.0.JavaSE_020", javax.swing.plaf; version\="0.0.0.JavaSE_020", javax.swing.filechooser; version\="0.0.0.JavaSE_020", javax.imageio.event; version\="0.0.0.JavaSE_020", javax.sound.sampled; version\="0.0.0.JavaSE_020", javax.print.attribute; version\="0.0.0.JavaSE_020", javax.print; version\="0.0.0.JavaSE_020", javax.swing.plaf.nimbus; version\="0.0.0.JavaSE_020", java.lang.instrument; version\="0.0.0.JavaSE_020", java.util.logging; version\="0.0.0.JavaSE_020", javax.management.remote; version\="0.0.0.JavaSE_020", javax.management.monitor; version\="0.0.0.JavaSE_020", javax.management.modelmbean; version\="0.0.0.JavaSE_020", javax.management.timer; version\="0.0.0.JavaSE_020", javax.management; version\="0.0.0.JavaSE_020", javax.management.relation; version\="0.0.0.JavaSE_020", javax.management.loading; version\="0.0.0.JavaSE_020", javax.management.openmbean; version\="0.0.0.JavaSE_020", java.lang.management; version\="0.0.0.JavaSE_020", javax.management.remote.rmi; version\="0.0.0.JavaSE_020", javax.naming; version\="0.0.0.JavaSE_020", javax.naming.spi; version\="0.0.0.JavaSE_020", javax.naming.event; version\="0.0.0.JavaSE_020", javax.naming.ldap.spi; version\="0.0.0.JavaSE_020", javax.naming.ldap; version\="0.0.0.JavaSE_020", javax.naming.directory; version\="0.0.0.JavaSE_020", java.net.http; version\="0.0.0.JavaSE_020", java.util.prefs; version\="0.0.0.JavaSE_020", javax.rmi.ssl; version\="0.0.0.JavaSE_020", java.rmi.dgc; version\="0.0.0.JavaSE_020", java.rmi; version\="0.0.0.JavaSE_020", java.rmi.server; version\="0.0.0.JavaSE_020", java.rmi.registry; version\="0.0.0.JavaSE_020", javax.script; version\="0.0.0.JavaSE_020", javax.security.auth.kerberos; version\="0.0.0.JavaSE_020", org.ietf.jgss; version\="0.0.0.JavaSE_020", javax.security.sasl; version\="0.0.0.JavaSE_020", javax.smartcardio; version\="0.0.0.JavaSE_020", java.sql; version\="0.0.0.JavaSE_020", javax.sql; version\="0.0.0.JavaSE_020", javax.sql.rowset.spi; version\="0.0.0.JavaSE_020", javax.sql.rowset.serial; version\="0.0.0.JavaSE_020", javax.sql.rowset; version\="0.0.0.JavaSE_020", javax.transaction.xa; version\="0.0.0.JavaSE_020", org.w3c.dom.events; version\="0.0.0.JavaSE_020", org.w3c.dom.ranges; version\="0.0.0.JavaSE_020", org.w3c.dom.ls; version\="0.0.0.JavaSE_020", javax.xml.stream.util; version\="0.0.0.JavaSE_020", javax.xml.namespace; version\="0.0.0.JavaSE_020", javax.xml.transform.stax; version\="0.0.0.JavaSE_020", org.xml.sax.helpers; version\="0.0.0.JavaSE_020", org.w3c.dom.views; version\="0.0.0.JavaSE_020", org.w3c.dom.bootstrap; version\="0.0.0.JavaSE_020", org.w3c.dom; version\="0.0.0.JavaSE_020", javax.xml.transform.stream; version\="0.0.0.JavaSE_020", javax.xml.transform.dom; version\="0.0.0.JavaSE_020", javax.xml.validation; version\="0.0.0.JavaSE_020", javax.xml.parsers; version\="0.0.0.JavaSE_020", org.xml.sax.ext; version\="0.0.0.JavaSE_020", javax.xml; version\="0.0.0.JavaSE_020", javax.xml.transform.sax; version\="0.0.0.JavaSE_020", javax.xml.datatype; version\="0.0.0.JavaSE_020", javax.xml.catalog; version\="0.0.0.JavaSE_020", org.w3c.dom.traversal; version\="0.0.0.JavaSE_020", javax.xml.stream.events; version\="0.0.0.JavaSE_020", javax.xml.stream; version\="0.0.0.JavaSE_020", org.xml.sax; version\="0.0.0.JavaSE_020", javax.xml.transform; version\="0.0.0.JavaSE_020", javax.xml.xpath; version\="0.0.0.JavaSE_020", javax.xml.crypto; version\="0.0.0.JavaSE_020", javax.xml.crypto.dsig; version\="0.0.0.JavaSE_020", javax.xml.crypto.dsig.spec; version\="0.0.0.JavaSE_020", javax.xml.crypto.dsig.keyinfo; version\="0.0.0.JavaSE_020", javax.xml.crypto.dsig.dom; version\="0.0.0.JavaSE_020", javax.xml.crypto.dom; version\="0.0.0.JavaSE_020", com.sun.java.accessibility.util; version\="0.0.0.JavaSE_020", com.sun.tools.attach; version\="0.0.0.JavaSE_020", com.sun.tools.attach.spi; version\="0.0.0.JavaSE_020", com.sun.source.tree; version\="0.0.0.JavaSE_020", com.sun.source.util; version\="0.0.0.JavaSE_020", com.sun.tools.javac; version\="0.0.0.JavaSE_020", com.sun.source.doctree; version\="0.0.0.JavaSE_020", jdk.dynalink.support; version\="0.0.0.JavaSE_020", jdk.dynalink; version\="0.0.0.JavaSE_020", jdk.dynalink.linker; version\="0.0.0.JavaSE_020", jdk.dynalink.beans; version\="0.0.0.JavaSE_020", jdk.dynalink.linker.support; version\="0.0.0.JavaSE_020", com.sun.net.httpserver; version\="0.0.0.JavaSE_020", com.sun.net.httpserver.spi; version\="0.0.0.JavaSE_020", com.sun.jarsigner; version\="0.0.0.JavaSE_020", jdk.security.jarsigner; version\="0.0.0.JavaSE_020", jdk.javadoc.doclet; version\="0.0.0.JavaSE_020", com.sun.tools.jconsole; version\="0.0.0.JavaSE_020", com.sun.jdi; version\="0.0.0.JavaSE_020", com.sun.jdi.request; version\="0.0.0.JavaSE_020", com.sun.jdi.connect; version\="0.0.0.JavaSE_020", com.sun.jdi.event; version\="0.0.0.JavaSE_020", com.sun.jdi.connect.spi; version\="0.0.0.JavaSE_020", jdk.jfr.consumer; version\="0.0.0.JavaSE_020", jdk.jfr; version\="0.0.0.JavaSE_020", jdk.jshell.spi; version\="0.0.0.JavaSE_020", jdk.jshell.tool; version\="0.0.0.JavaSE_020", jdk.jshell; version\="0.0.0.JavaSE_020", jdk.jshell.execution; version\="0.0.0.JavaSE_020", netscape.javascript; version\="0.0.0.JavaSE_020", com.sun.management; version\="0.0.0.JavaSE_020", jdk.management.jfr; version\="0.0.0.JavaSE_020", jdk.net; version\="0.0.0.JavaSE_020", jdk.nio; version\="0.0.0.JavaSE_020", jdk.nio.mapmode; version\="0.0.0.JavaSE_020", com.sun.nio.sctp; version\="0.0.0.JavaSE_020", com.sun.security.auth.login; version\="0.0.0.JavaSE_020", com.sun.security.auth; version\="0.0.0.JavaSE_020", com.sun.security.auth.callback; version\="0.0.0.JavaSE_020", com.sun.security.auth.module; version\="0.0.0.JavaSE_020", com.sun.security.jgss; version\="0.0.0.JavaSE_020", sun.reflect; version\="0.0.0.JavaSE_020", sun.misc; version\="0.0.0.JavaSE_020", com.sun.nio.file; version\="0.0.0.JavaSE_020", jdk.swing.interop; version\="0.0.0.JavaSE_020", org.w3c.dom.xpath; version\="0.0.0.JavaSE_020", org.w3c.dom.css; version\="0.0.0.JavaSE_020", org.w3c.dom.stylesheets; version\="0.0.0.JavaSE_020", org.w3c.dom.html; version\="0.0.0.JavaSE_020", com.yahoo.jdisc, com.yahoo.jdisc.application, com.yahoo.jdisc.handler, com.yahoo.jdisc.service, com.yahoo.jdisc.statistics, com.yahoo.jdisc.refcount, javax.inject;version\=1.0.0, org.aopalliance.intercept, org.aopalliance.aop, com.google.common.annotations;version\="27.1.0",com.google.common.base;version\="27.1.0",com.google.common.cache;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.util.concurrent",com.google.common.collect;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.escape;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.eventbus;version\="27.1.0",com.google.common.graph;version\="27.1.0";uses\:\="com.google.common.collect",com.google.common.hash;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.html;version\="27.1.0";uses\:\="com.google.common.escape",com.google.common.io;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.graph,com.google.common.hash",com.google.common.math;version\="27.1.0",com.google.common.net;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.escape",com.google.common.primitives;version\="27.1.0";uses\:\="com.google.common.base",com.google.common.reflect;version\="27.1.0";uses\:\="com.google.common.collect,com.google.common.io",com.google.common.util.concurrent;version\="27.1.0";uses\:\="com.google.common.base,com.google.common.collect,com.google.common.util.concurrent.internal",com.google.common.xml;version\="27.1.0";uses\:\="com.google.common.escape", com.google.inject;version\="1.4",com.google.inject.binder;version\="1.4",com.google.inject.matcher;version\="1.4",com.google.inject.multibindings;version\="1.4",com.google.inject.name;version\="1.4",com.google.inject.spi;version\="1.4",com.google.inject.util;version\="1.4", org.slf4j;version\=1.7.32, org.slf4j.spi;version\=1.7.32, org.slf4j.helpers;version\=1.7.32, org.slf4j.event;version\=1.7.32, org.slf4j.impl;version\=1.7.32, org.apache.commons.logging;version\=1.2, org.apache.commons.logging.impl;version\=1.2, com.sun.jna;version\=5.11.0, com.sun.jna.ptr;version\=5.11.0, com.sun.jna.win32;version\=5.11.0, org.apache.log4j;version\=1.2.17,org.apache.log4j.helpers;version\=1.2.17,org.apache.log4j.spi;version\=1.2.17,org.apache.log4j.xml;version\=1.2.17, com.yahoo.component.annotation;version\="1.0.0", com.yahoo.config;version\=1.0.0, com.yahoo.vespa.defaults;version\=1.0.0, ai.vespa.http;version\=1.0.0,ai.vespa.llm.completion;version\=1.0.0,ai.vespa.llm.test;version\=1.0.0,ai.vespa.llm;version\=1.0.0,ai.vespa.validation;version\=1.0.0,com.yahoo.binaryprefix;version\=1.0.0,com.yahoo.collections;version\=1.0.0,com.yahoo.compress;version\=1.0.0,com.yahoo.concurrent.classlock;version\=1.0.0,com.yahoo.concurrent.maintenance;version\=1.0.0,com.yahoo.concurrent;version\=1.0.0,com.yahoo.data.access.simple;version\=1.0.0,com.yahoo.data.access.slime;version\=1.0.0,com.yahoo.data.access;version\=1.0.0,com.yahoo.errorhandling;version\=1.0.0,com.yahoo.exception;version\=1.0.0,com.yahoo.geo;version\=1.0.0,com.yahoo.io.reader;version\=1.0.0,com.yahoo.io;version\=1.0.0,com.yahoo.javacc;version\=1.0.0,com.yahoo.lang;version\=1.0.0,com.yahoo.nativec;version\=1.0.0,com.yahoo.net;version\=1.0.0,com.yahoo.path;version\=1.0.0,com.yahoo.protect;version\=1.0.0,com.yahoo.reflection;version\=1.0.0,com.yahoo.slime;version\=1.0.0,com.yahoo.stream;version\=1.0.0,com.yahoo.system.execution;version\=1.0.0,com.yahoo.system;version\=1.0.0,com.yahoo.tensor.evaluation;version\=1.0.0,com.yahoo.tensor.functions;version\=1.0.0,com.yahoo.tensor.serialization;version\=1.0.0,com.yahoo.tensor;version\=1.0.0,com.yahoo.text.internal;version\=1.0.0,com.yahoo.text;version\=1.0.0,com.yahoo.time;version\=1.0.0,com.yahoo.transaction;version\=1.0.0,com.yahoo.vespa.objects;version\=1.0.0,com.yahoo.yolean.chain;version\=1.0.0,com.yahoo.yolean.concurrent;version\=1.0.0,com.yahoo.yolean.function;version\=1.0.0,com.yahoo.yolean.system;version\=1.0.0,com.yahoo.yolean.trace;version\=1.0.0,com.yahoo.yolean;version\=1.0.0, com.yahoo.log.event;version\=1.0.0,com.yahoo.log.impl;version\=1.0.0,com.yahoo.log;version\=1.0.0, javax.xml.bind;version\="2.3";uses\:\="javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.validation,org.w3c.dom,org.xml.sax",javax.xml.bind.annotation;version\="2.3";uses\:\="javax.xml.bind,javax.xml.parsers,javax.xml.transform,javax.xml.transform.dom,org.w3c.dom",javax.xml.bind.annotation.adapters;version\="2.3",javax.xml.bind.attachment;version\="2.3";uses\:\="javax.activation",javax.xml.bind.helpers;version\="2.3";uses\:\="javax.xml.bind,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.stream,javax.xml.transform,javax.xml.validation,org.w3c.dom,org.xml.sax",javax.xml.bind.util;version\="2.3";uses\:\="javax.xml.bind,javax.xml.transform.sax", com.sun.istack;version\="3.0.5";uses\:\="javax.activation,javax.xml.stream,org.xml.sax,org.xml.sax.helpers",com.sun.istack.localization;version\="3.0.5",com.sun.istack.logging;version\="3.0.5",com.sun.xml.bind;uses\:\="org.xml.sax";version\="2.3.0",com.sun.xml.bind.annotation;version\="2.3.0",com.sun.xml.bind.api;uses\:\="org.xml.sax";version\="2.3.0",com.sun.xml.bind.api.impl;version\="2.3.0",com.sun.xml.bind.marshaller;uses\:\="javax.xml.parsers,org.w3c.dom,org.xml.sax,org.xml.sax.helpers";version\="2.3.0",com.sun.xml.bind.unmarshaller;uses\:\="com.sun.xml.bind.v2.runtime.unmarshaller,javax.xml.bind,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.util;version\="2.3.0",com.sun.xml.bind.v2;version\="2.3.0",com.sun.xml.bind.v2.model.annotation;uses\:\="com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.runtime";version\="2.3.0",com.sun.xml.bind.v2.model.core;uses\:\="com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.impl,com.sun.xml.bind.v2.model.nav,com.sun.xml.bind.v2.runtime,javax.activation,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.namespace,javax.xml.transform";version\="2.3.0",com.sun.xml.bind.v2.model.impl;uses\:\="com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.nav";version\="2.3.0",com.sun.xml.bind.v2.model.nav;uses\:\="com.sun.xml.bind.v2.runtime";version\="2.3.0",com.sun.xml.bind.v2.model.util;uses\:\="javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.runtime;uses\:\="com.sun.xml.bind.v2.model.annotation,javax.activation,javax.xml.bind,javax.xml.bind.annotation.adapters";version\="2.3.0",com.sun.xml.bind.v2.runtime.unmarshaller;uses\:\="javax.xml.bind,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.schemagen.episode;uses\:\="com.sun.xml.txw2,com.sun.xml.txw2.annotation";version\="2.3.0",com.sun.xml.bind.v2.util;uses\:\="javax.xml.parsers,javax.xml.transform,javax.xml.validation,javax.xml.xpath";version\="2.3.0",com.sun.xml.txw2;uses\:\="com.sun.xml.txw2.output,javax.xml.namespace";version\="2.3.0",com.sun.xml.txw2.annotation;version\="2.3.0",com.sun.xml.txw2.output;uses\:\="com.sun.xml.txw2,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stream,org.w3c.dom,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers";version\="2.3.0", com.sun.xml.bind;uses\:\="com.sun.xml.bind.v2.runtime.reflect,javax.xml.bind,javax.xml.bind.annotation.adapters,javax.xml.datatype,javax.xml.namespace,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.api;uses\:\="com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,javax.xml.bind,javax.xml.bind.attachment,javax.xml.namespace,javax.xml.stream,javax.xml.transform,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.marshaller;version\="2.3.0",com.sun.xml.bind.unmarshaller;uses\:\="org.xml.sax";version\="2.3.0",com.sun.xml.bind.util;uses\:\="com.sun.xml.bind,javax.xml.bind.helpers,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.annotation,javax.xml.bind";version\="2.3.0",com.sun.xml.bind.v2.bytecode;version\="2.3.0",com.sun.xml.bind.v2.model.annotation;uses\:\="com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.nav,com.sun.xml.bind.v2.runtime";version\="2.3.0",com.sun.xml.bind.v2.model.impl;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.nav,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,javax.activation,javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.model.runtime;uses\:\="com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.reflect,javax.xml.bind,javax.xml.namespace,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime;uses\:\="com.sun.istack,com.sun.xml.bind.api,com.sun.xml.bind.marshaller,com.sun.xml.bind.v2.model.annotation,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime.output,com.sun.xml.bind.v2.runtime.property,com.sun.xml.bind.v2.runtime.unmarshaller,javax.activation,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.transform.sax,javax.xml.validation,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.output;uses\:\="com.sun.xml.bind.marshaller,com.sun.xml.bind.v2.runtime,com.sun.xml.fastinfoset.stax,javax.xml.stream,org.jvnet.staxex,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.property;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.reflect,com.sun.xml.bind.v2.runtime.unmarshaller,com.sun.xml.bind.v2.util,javax.xml.namespace,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.reflect;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.unmarshaller,javax.xml.bind,javax.xml.bind.annotation.adapters,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.reflect.opt;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.runtime,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.reflect,javax.xml.stream,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.runtime.unmarshaller;uses\:\="com.sun.xml.bind,com.sun.xml.bind.api,com.sun.xml.bind.unmarshaller,com.sun.xml.bind.util,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.output,com.sun.xml.bind.v2.runtime.reflect,javax.activation,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.namespace,javax.xml.stream,javax.xml.transform,javax.xml.transform.sax,javax.xml.validation,org.w3c.dom,org.xml.sax";version\="2.3.0",com.sun.xml.bind.v2.schemagen;uses\:\="com.sun.xml.bind.api,com.sun.xml.bind.v2.model.core,com.sun.xml.bind.v2.model.nav,com.sun.xml.txw2.output,javax.xml.bind,javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.schemagen.xmlschema;uses\:\="com.sun.xml.txw2,com.sun.xml.txw2.annotation,javax.xml.namespace";version\="2.3.0",com.sun.xml.bind.v2.util;uses\:\="com.sun.xml.bind.v2.runtime,com.sun.xml.bind.v2.runtime.unmarshaller,javax.activation,javax.xml.namespace,javax.xml.transform.stream,org.xml.sax";version\="2.3.0", javax.activation;uses\:\="com.sun.activation.registries";version\="1.2",com.sun.activation.viewers;uses\:\="javax.activation";version\="1.2.0",com.sun.activation.registries;version\="1.2.0" diff --git a/model-integration/abi-spec.json b/model-integration/abi-spec.json index 0c76ba38660..d3c472778e6 100644 --- a/model-integration/abi-spec.json +++ b/model-integration/abi-spec.json @@ -1,41 +1,5 @@ { - "ai.vespa.llm.Completion$FinishReason" : { - "superClass" : "java.lang.Enum", - "interfaces" : [ ], - "attributes" : [ - "public", - "final", - "enum" - ], - "methods" : [ - "public static ai.vespa.llm.Completion$FinishReason[] values()", - "public static ai.vespa.llm.Completion$FinishReason valueOf(java.lang.String)" - ], - "fields" : [ - "public static final enum ai.vespa.llm.Completion$FinishReason length", - "public static final enum ai.vespa.llm.Completion$FinishReason stop" - ] - }, - "ai.vespa.llm.Completion" : { - "superClass" : "java.lang.Record", - "interfaces" : [ ], - "attributes" : [ - "public", - "final", - "record" - ], - "methods" : [ - "public void (java.lang.String, ai.vespa.llm.Completion$FinishReason)", - "public java.lang.String text()", - "public ai.vespa.llm.Completion$FinishReason finishReason()", - "public static ai.vespa.llm.Completion from(java.lang.String)", - "public final java.lang.String toString()", - "public final int hashCode()", - "public final boolean equals(java.lang.Object)" - ], - "fields" : [ ] - }, - "ai.vespa.llm.Generator" : { + "ai.vespa.llm.generation.Generator" : { "superClass" : "com.yahoo.component.AbstractComponent", "interfaces" : [ ], "attributes" : [ @@ -43,13 +7,13 @@ ], "methods" : [ "public void (ai.vespa.modelintegration.evaluator.OnnxRuntime, com.yahoo.llm.GeneratorConfig)", - "public java.lang.String generate(java.lang.String, ai.vespa.llm.GeneratorOptions)", + "public java.lang.String generate(java.lang.String, ai.vespa.llm.generation.GeneratorOptions)", "public java.lang.String generate(java.lang.String)", "public void deconstruct()" ], "fields" : [ ] }, - "ai.vespa.llm.GeneratorOptions$SearchMethod" : { + "ai.vespa.llm.generation.GeneratorOptions$SearchMethod" : { "superClass" : "java.lang.Enum", "interfaces" : [ ], "attributes" : [ @@ -58,17 +22,17 @@ "enum" ], "methods" : [ - "public static ai.vespa.llm.GeneratorOptions$SearchMethod[] values()", - "public static ai.vespa.llm.GeneratorOptions$SearchMethod valueOf(java.lang.String)" + "public static ai.vespa.llm.generation.GeneratorOptions$SearchMethod[] values()", + "public static ai.vespa.llm.generation.GeneratorOptions$SearchMethod valueOf(java.lang.String)" ], "fields" : [ - "public static final enum ai.vespa.llm.GeneratorOptions$SearchMethod GREEDY", - "public static final enum ai.vespa.llm.GeneratorOptions$SearchMethod CONTRASTIVE", - "public static final enum ai.vespa.llm.GeneratorOptions$SearchMethod BEAM", - "public static final enum ai.vespa.llm.GeneratorOptions$SearchMethod SAMPLE" + "public static final enum ai.vespa.llm.generation.GeneratorOptions$SearchMethod GREEDY", + "public static final enum ai.vespa.llm.generation.GeneratorOptions$SearchMethod CONTRASTIVE", + "public static final enum ai.vespa.llm.generation.GeneratorOptions$SearchMethod BEAM", + "public static final enum ai.vespa.llm.generation.GeneratorOptions$SearchMethod SAMPLE" ] }, - "ai.vespa.llm.GeneratorOptions" : { + "ai.vespa.llm.generation.GeneratorOptions" : { "superClass" : "java.lang.Object", "interfaces" : [ ], "attributes" : [ @@ -76,109 +40,10 @@ ], "methods" : [ "public void ()", - "public ai.vespa.llm.GeneratorOptions$SearchMethod getSearchMethod()", - "public ai.vespa.llm.GeneratorOptions setSearchMethod(ai.vespa.llm.GeneratorOptions$SearchMethod)", + "public ai.vespa.llm.generation.GeneratorOptions$SearchMethod getSearchMethod()", + "public ai.vespa.llm.generation.GeneratorOptions setSearchMethod(ai.vespa.llm.generation.GeneratorOptions$SearchMethod)", "public int getMaxLength()", - "public ai.vespa.llm.GeneratorOptions setMaxLength(int)" - ], - "fields" : [ ] - }, - "ai.vespa.llm.LanguageModel" : { - "superClass" : "java.lang.Object", - "interfaces" : [ ], - "attributes" : [ - "public", - "interface", - "abstract" - ], - "methods" : [ - "public abstract java.util.List complete(ai.vespa.llm.Prompt)" - ], - "fields" : [ ] - }, - "ai.vespa.llm.Prompt" : { - "superClass" : "java.lang.Object", - "interfaces" : [ ], - "attributes" : [ - "public", - "abstract" - ], - "methods" : [ - "public void ()", - "public abstract java.lang.String asString()", - "public ai.vespa.llm.Prompt append(ai.vespa.llm.Completion)", - "public abstract ai.vespa.llm.Prompt append(java.lang.String)" - ], - "fields" : [ ] - }, - "ai.vespa.llm.StringPrompt" : { - "superClass" : "ai.vespa.llm.Prompt", - "interfaces" : [ ], - "attributes" : [ - "public" - ], - "methods" : [ - "public java.lang.String asString()", - "public ai.vespa.llm.StringPrompt append(java.lang.String)", - "public ai.vespa.llm.StringPrompt append(ai.vespa.llm.Completion)", - "public java.lang.String toString()", - "public static ai.vespa.llm.StringPrompt from(java.lang.String)", - "public bridge synthetic ai.vespa.llm.Prompt append(java.lang.String)", - "public bridge synthetic ai.vespa.llm.Prompt append(ai.vespa.llm.Completion)" - ], - "fields" : [ ] - }, - "ai.vespa.llm.client.OpenAiClient$Builder" : { - "superClass" : "java.lang.Object", - "interfaces" : [ ], - "attributes" : [ - "public" - ], - "methods" : [ - "public void (java.lang.String)", - "public ai.vespa.llm.client.OpenAiClient$Builder model(java.lang.String)", - "public ai.vespa.llm.client.OpenAiClient$Builder echo(boolean)", - "public ai.vespa.llm.client.OpenAiClient build()" - ], - "fields" : [ ] - }, - "ai.vespa.llm.client.OpenAiClient" : { - "superClass" : "java.lang.Object", - "interfaces" : [ - "ai.vespa.llm.LanguageModel" - ], - "attributes" : [ - "public" - ], - "methods" : [ - "public java.util.List complete(ai.vespa.llm.Prompt)" - ], - "fields" : [ ] - }, - "ai.vespa.llm.test.MockLanguageModel$Builder" : { - "superClass" : "java.lang.Object", - "interfaces" : [ ], - "attributes" : [ - "public" - ], - "methods" : [ - "public ai.vespa.llm.test.MockLanguageModel$Builder completer(java.util.function.Function)", - "public void ()", - "public ai.vespa.llm.test.MockLanguageModel build()" - ], - "fields" : [ ] - }, - "ai.vespa.llm.test.MockLanguageModel" : { - "superClass" : "java.lang.Object", - "interfaces" : [ - "ai.vespa.llm.LanguageModel" - ], - "attributes" : [ - "public" - ], - "methods" : [ - "public void (ai.vespa.llm.test.MockLanguageModel$Builder)", - "public java.util.List complete(ai.vespa.llm.Prompt)" + "public ai.vespa.llm.generation.GeneratorOptions setMaxLength(int)" ], "fields" : [ ] } diff --git a/model-integration/pom.xml b/model-integration/pom.xml index c96441f11a7..c27ed9d2c31 100644 --- a/model-integration/pom.xml +++ b/model-integration/pom.xml @@ -110,11 +110,6 @@ lz4-java - - com.theokanning.openai-gpt3-java - service - - junit junit @@ -151,18 +146,6 @@ org.apache.maven.plugins maven-compiler-plugin - - - - -Xlint:all - -Xlint:-rawtypes - -Xlint:-unchecked - -Xlint:-serial - - com.github.os72 diff --git a/model-integration/src/main/java/ai/vespa/llm/Completion.java b/model-integration/src/main/java/ai/vespa/llm/Completion.java deleted file mode 100644 index 5f483a65186..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/Completion.java +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package ai.vespa.llm; - -import com.yahoo.api.annotations.Beta; - -import java.util.Objects; - -/** - * A completion from a language model. - * - * @author bratseth - */ -@Beta -public record Completion(String text, FinishReason finishReason) { - - public enum FinishReason { - - /** The maximum length of a completion was reached. */ - length, - - /** The completion is the predicted ending of the prompt. */ - stop - - } - - public Completion(String text, FinishReason finishReason) { - this.text = Objects.requireNonNull(text); - this.finishReason = Objects.requireNonNull(finishReason); - } - - /** Returns the generated text completion. */ - public String text() { return text; } - - /** Returns the reason this completion ended. */ - public FinishReason finishReason() { return finishReason; } - - public static Completion from(String text) { - return new Completion(text, FinishReason.stop); - } - -} diff --git a/model-integration/src/main/java/ai/vespa/llm/Generator.java b/model-integration/src/main/java/ai/vespa/llm/Generator.java deleted file mode 100644 index 6b60041947b..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/Generator.java +++ /dev/null @@ -1,232 +0,0 @@ -package ai.vespa.llm; - -import ai.vespa.modelintegration.evaluator.OnnxEvaluator; -import ai.vespa.modelintegration.evaluator.OnnxEvaluatorOptions; -import ai.vespa.modelintegration.evaluator.OnnxRuntime; -import com.yahoo.component.AbstractComponent; -import com.yahoo.component.annotation.Inject; -import com.yahoo.language.process.Embedder; -import com.yahoo.language.sentencepiece.SentencePieceEmbedder; -import com.yahoo.llm.GeneratorConfig; -import com.yahoo.tensor.DimensionSizes; -import com.yahoo.tensor.IndexedTensor; -import com.yahoo.tensor.PartialAddress; -import com.yahoo.tensor.Tensor; -import com.yahoo.tensor.TensorType; -import com.yahoo.api.annotations.Beta; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -/** -* A text generator based on language models (LLMs). By configuring a - * sentencepience tokenizer and models for encoding and decoding, this - * component generates text based on the given prompt. - * - * See llm.generator.def for configurable parameters. - * - * @author lesters - */ -@Beta -public class Generator extends AbstractComponent { - - private final static int TOKEN_EOS = 1; // end of sequence - - private final static String BATCH_DIMENSION = "d0"; - private final static String SEQUENCE_DIMENSION = "d1"; - - private final int tokenizerMaxTokens; - private final String encoderInputIdsName; - private final String encoderAttentionMaskName; - private final String encoderOutputName; - private final String decoderInputIdsName; - private final String decoderAttentionMaskName; - private final String decoderEncoderHiddenStateName; - private final String decoderOutputName; - - private final SentencePieceEmbedder tokenizer; - private final OnnxEvaluator encoder; - private final OnnxEvaluator decoder; - - @Inject - public Generator(OnnxRuntime onnx, GeneratorConfig config) { - // Set up tokenizer - tokenizer = new SentencePieceEmbedder.Builder(config.tokenizerModel().toString()).build(); - tokenizerMaxTokens = config.tokenizerMaxTokens(); - - // Set up encoder - encoderInputIdsName = config.encoderModelInputIdsName(); - encoderAttentionMaskName = config.encoderModelAttentionMaskName(); - encoderOutputName = config.encoderModelOutputName(); - - OnnxEvaluatorOptions encoderOptions = new OnnxEvaluatorOptions(); - encoderOptions.setExecutionMode(config.encoderOnnxExecutionMode().toString()); - encoderOptions.setInterOpThreads(modifyThreadCount(config.encoderOnnxInterOpThreads())); - encoderOptions.setIntraOpThreads(modifyThreadCount(config.encoderOnnxIntraOpThreads())); - - encoder = onnx.evaluatorOf(config.encoderModel().toString(), encoderOptions); - - // Set up decoder - decoderInputIdsName = config.decoderModelInputIdsName(); - decoderAttentionMaskName = config.decoderModelAttentionMaskName(); - decoderEncoderHiddenStateName = config.decoderModelEncoderHiddenStateName(); - decoderOutputName = config.decoderModelOutputName(); - - OnnxEvaluatorOptions decoderOptions = new OnnxEvaluatorOptions(); - decoderOptions.setExecutionMode(config.decoderOnnxExecutionMode().toString()); - decoderOptions.setInterOpThreads(modifyThreadCount(config.decoderOnnxInterOpThreads())); - decoderOptions.setIntraOpThreads(modifyThreadCount(config.decoderOnnxIntraOpThreads())); - - decoder = onnx.evaluatorOf(config.decoderModel().toString(), decoderOptions); - - validateModels(); - } - - /** - * Generates text by evaluating an encoder model to encode the prompt, and - * repeatedly evaluating a decoding model to generate tokens until some - * stopping criteria has been met. - * - * @param prompt the prompt to generate text from - * @param options options for text generation - * @return a text generated from the prompt - */ - public String generate(String prompt, GeneratorOptions options) { - return switch (options.getSearchMethod()) { - case GREEDY -> generateGreedy(prompt, options); - default -> generateNotImplemented(options); - }; - } - - public String generate(String prompt) { - return generate(prompt, new GeneratorOptions()); - } - - @Override public void deconstruct() { encoder.close(); decoder.close(); } - - private String generateNotImplemented(GeneratorOptions options) { - throw new UnsupportedOperationException("Search method '" + options.getSearchMethod() + "' is currently not implemented"); - } - - private String generateGreedy(String prompt, GeneratorOptions options) { - var generatedTokens = new ArrayList(); - generatedTokens.add(0); // Or target tokens - - // Tokenize - var inputTokens = tokenize(prompt); // Or source tokens - - // Evaluate encoder - var encoderInput = createTensorRepresentation(inputTokens, SEQUENCE_DIMENSION); - var encoderMask = createAttentionMask(encoderInput).expand(BATCH_DIMENSION); - var encoderOutput = evaluateEncoder(encoderInput.expand(BATCH_DIMENSION), encoderMask); - - // Greedy search just grabs the next most probable token - while (generatedTokens.size() < options.getMaxLength()) { // Todo: add stopping criteria - var decoderInput = createTensorRepresentation(generatedTokens, SEQUENCE_DIMENSION).expand(BATCH_DIMENSION); - var logits = evaluateDecoder(decoderInput, encoderMask, encoderOutput); - var nextToken = findMostProbableToken(logits, generatedTokens.size()-1, BATCH_DIMENSION, SEQUENCE_DIMENSION); - generatedTokens.add(nextToken); - } - - return detokenize(generatedTokens); - } - - private Tensor evaluateEncoder(Tensor input, Tensor mask) { - var encoderInputs = Map.of(encoderInputIdsName, input, - encoderAttentionMaskName, mask); - return encoder.evaluate(encoderInputs, encoderOutputName); - } - - private IndexedTensor evaluateDecoder(Tensor input, Tensor encoderMask, Tensor encoderOutput) { - var inputs = Map.of(decoderInputIdsName, input, - decoderAttentionMaskName, encoderMask, // yes, encoder's attention mask - decoderEncoderHiddenStateName, encoderOutput); - var output = decoder.evaluate(inputs, decoderOutputName); - if ( ! (output instanceof IndexedTensor indexedTensor)) { - throw new IllegalArgumentException("Output of decoder model is not an 'IndexedTensor'"); - } - return indexedTensor; - } - - /** - * Given a tensor 'logits' with 3 dimensions: batch, sequence, and vocabulary - * find the value in the vocabulary dimension with highest score for the given - * token in the sequence - */ - private static int findMostProbableToken(IndexedTensor logits, int seqIndex, String batchDim, String seqDim) { - if (logits.type().rank() != 3) { - throw new IllegalArgumentException("Expected a tensor with rank 3: batch, sequence, and vocabulary size. " + - "Got: " + logits.type()); - } - var iterator = logits.cellIterator(new PartialAddress.Builder(2). - add(batchDim, 0). - add(seqDim, seqIndex).build(), - DimensionSizes.of(logits.type())); - var maxVal = iterator.next().getValue(); - int maxIndex = 0; - for (int i = 1; iterator.hasNext(); ++i) { - var val = iterator.next().getValue(); - if (val >= maxVal && i != TOKEN_EOS) { - maxVal = val; - maxIndex = i; - } - } - return maxIndex; - } - - private List tokenize(String text) { - var tokens = tokenizer.embed(text, new Embedder.Context("tokenizer")); - tokens = tokens.size() >= tokenizerMaxTokens ? tokens.subList(0,tokenizerMaxTokens-1): tokens; - tokens.add(TOKEN_EOS); - return tokens; - } - - private String detokenize(List tokens) { - return tokenizer.decode(tokens, new Embedder.Context("tokenizer"), true); - } - - private static Tensor createTensorRepresentation(List tokens, String dimension) { - var size = tokens.size(); - TensorType type = new TensorType.Builder(TensorType.Value.FLOAT).indexed(dimension, size).build(); - IndexedTensor.Builder builder = IndexedTensor.Builder.of(type); - for (int i = 0; i < size; ++i) { - builder.cell(tokens.get(i), i); - } - return builder.build(); - } - - private static Tensor createAttentionMask(Tensor d) { - return d.map((x) -> x > 0 ? 1:0); - } - - private void validateModels() { - Map inputs = encoder.getInputInfo(); - validateName(inputs, encoderInputIdsName, "input"); - validateName(inputs, encoderAttentionMaskName, "input"); - - Map outputs = encoder.getOutputInfo(); - validateName(outputs, encoderOutputName, "output"); - - inputs = decoder.getInputInfo(); - validateName(inputs, decoderInputIdsName, "input"); - validateName(inputs, decoderAttentionMaskName, "input"); - validateName(inputs, decoderEncoderHiddenStateName, "input"); - - outputs = decoder.getOutputInfo(); - validateName(outputs, decoderOutputName, "output"); - } - - private void validateName(Map types, String name, String type) { - if ( ! types.containsKey(name)) { - throw new IllegalArgumentException("Model does not contain required " + type + ": '" + name + "'. " + - "Model contains: " + String.join(",", types.keySet())); - } - } - - private int modifyThreadCount(int numThreads) { - if (numThreads >= 0) - return numThreads; - return Math.max(1, (int) Math.ceil(((double) Runtime.getRuntime().availableProcessors()) / (-1 * numThreads))); - } -} diff --git a/model-integration/src/main/java/ai/vespa/llm/GeneratorOptions.java b/model-integration/src/main/java/ai/vespa/llm/GeneratorOptions.java deleted file mode 100644 index 8b490a733dd..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/GeneratorOptions.java +++ /dev/null @@ -1,37 +0,0 @@ -package ai.vespa.llm; - -import com.yahoo.api.annotations.Beta; - -@Beta -public class GeneratorOptions { - - public enum SearchMethod { - GREEDY, - CONTRASTIVE, - BEAM, - SAMPLE, - } - - private SearchMethod searchMethod = SearchMethod.GREEDY; - private int maxLength = 20; - - public SearchMethod getSearchMethod() { - return searchMethod; - } - - public GeneratorOptions setSearchMethod(SearchMethod searchMethod) { - this.searchMethod = searchMethod; - return this; - } - - public int getMaxLength() { - return maxLength; - } - - public GeneratorOptions setMaxLength(int maxLength) { - this.maxLength = maxLength; - return this; - } - - -} diff --git a/model-integration/src/main/java/ai/vespa/llm/LanguageModel.java b/model-integration/src/main/java/ai/vespa/llm/LanguageModel.java deleted file mode 100644 index 0739162c5ee..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/LanguageModel.java +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package ai.vespa.llm; - -import com.yahoo.api.annotations.Beta; - -import java.util.List; - -/** - * Interface to language models. - * - * @author bratseth - */ -@Beta -public interface LanguageModel { - - List complete(Prompt prompt); - -} diff --git a/model-integration/src/main/java/ai/vespa/llm/Prompt.java b/model-integration/src/main/java/ai/vespa/llm/Prompt.java deleted file mode 100644 index 77093d5e21b..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/Prompt.java +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package ai.vespa.llm; - -import com.yahoo.api.annotations.Beta; - -/** - * A prompt that can be given to a large language model to generate a completion. - * - * @author bratseth - */ -@Beta -public abstract class Prompt { - - public abstract String asString(); - - /** Returns a new prompt with the text of the given completion appended. */ - public Prompt append(Completion completion) { - return append(completion.text()); - } - - public abstract Prompt append(String text); - -} diff --git a/model-integration/src/main/java/ai/vespa/llm/StringPrompt.java b/model-integration/src/main/java/ai/vespa/llm/StringPrompt.java deleted file mode 100644 index 0af8388dfb1..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/StringPrompt.java +++ /dev/null @@ -1,43 +0,0 @@ -package ai.vespa.llm; - -import com.yahoo.api.annotations.Beta; - -import java.util.Objects; - -/** - * A prompt which just consists of a string. - * - * @author bratseth - */ -@Beta -public class StringPrompt extends Prompt { - - private final String string; - - private StringPrompt(String string) { - this.string = Objects.requireNonNull(string); - } - - @Override - public String asString() { return string; } - - @Override - public StringPrompt append(String text) { - return StringPrompt.from(string + text); - } - - @Override - public StringPrompt append(Completion completion) { - return append(completion.text()); - } - - @Override - public String toString() { - return string; - } - - public static StringPrompt from(String string) { - return new StringPrompt(string); - } - -} diff --git a/model-integration/src/main/java/ai/vespa/llm/client/OpenAiClient.java b/model-integration/src/main/java/ai/vespa/llm/client/OpenAiClient.java deleted file mode 100644 index 3f4475b2482..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/client/OpenAiClient.java +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package ai.vespa.llm.client; - -import ai.vespa.llm.Completion; -import ai.vespa.llm.LanguageModel; -import ai.vespa.llm.Prompt; -import com.theokanning.openai.OpenAiHttpException; -import com.theokanning.openai.completion.CompletionRequest; -import com.theokanning.openai.service.OpenAiService; -import com.yahoo.api.annotations.Beta; -import com.yahoo.yolean.Exceptions; - -import java.util.List; - -/** - * A client to the OpenAI language model API. Refer to https://platform.openai.com/docs/api-reference/. - * - * @author bratseth - */ -@Beta -public class OpenAiClient implements LanguageModel { - - private final OpenAiService openAiService; - private final String model; - private final boolean echo; - - private OpenAiClient(Builder builder) { - openAiService = new OpenAiService(builder.token); - this.model = builder.model; - this.echo = builder.echo; - } - - @Override - public List complete(Prompt prompt) { - try { - CompletionRequest completionRequest = CompletionRequest.builder() - .prompt(prompt.asString()) - .model(model) - .echo(echo) - .build(); - return openAiService.createCompletion(completionRequest).getChoices().stream() - .map(c -> new Completion(c.getText(), toFinishReason(c.getFinish_reason()))).toList(); - } - catch (OpenAiHttpException e) { - throw new RuntimeException(Exceptions.toMessageString(e)); - } - } - - private Completion.FinishReason toFinishReason(String finishReasonString) { - return switch(finishReasonString) { - case "length" -> Completion.FinishReason.length; - case "stop" -> Completion.FinishReason.stop; - default -> throw new IllegalStateException("Unknown OpenAi completion finish reason '" + finishReasonString + "'"); - }; - } - - public static class Builder { - - private final String token; - private String model = "text-davinci-003"; - private boolean echo = false; - - public Builder(String token) { - this.token = token; - } - - /** One of the language models listed at https://platform.openai.com/docs/models */ - public Builder model(String model) { - this.model = model; - return this; - } - - public Builder echo(boolean echo) { - this.echo = echo; - return this; - } - - public OpenAiClient build() { - return new OpenAiClient(this); - } - - } - -} diff --git a/model-integration/src/main/java/ai/vespa/llm/client/package-info.java b/model-integration/src/main/java/ai/vespa/llm/client/package-info.java deleted file mode 100644 index c95f87eec3c..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/client/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -@ExportPackage -@PublicApi -package ai.vespa.llm.client; - -import com.yahoo.api.annotations.PublicApi; -import com.yahoo.osgi.annotation.ExportPackage; - -/** - * Clients to externally hosted large language models. - */ \ No newline at end of file diff --git a/model-integration/src/main/java/ai/vespa/llm/generation/Generator.java b/model-integration/src/main/java/ai/vespa/llm/generation/Generator.java new file mode 100644 index 00000000000..f20925b86ee --- /dev/null +++ b/model-integration/src/main/java/ai/vespa/llm/generation/Generator.java @@ -0,0 +1,232 @@ +package ai.vespa.llm.generation; + +import ai.vespa.modelintegration.evaluator.OnnxEvaluator; +import ai.vespa.modelintegration.evaluator.OnnxEvaluatorOptions; +import ai.vespa.modelintegration.evaluator.OnnxRuntime; +import com.yahoo.component.AbstractComponent; +import com.yahoo.component.annotation.Inject; +import com.yahoo.language.process.Embedder; +import com.yahoo.language.sentencepiece.SentencePieceEmbedder; +import com.yahoo.llm.GeneratorConfig; +import com.yahoo.tensor.DimensionSizes; +import com.yahoo.tensor.IndexedTensor; +import com.yahoo.tensor.PartialAddress; +import com.yahoo.tensor.Tensor; +import com.yahoo.tensor.TensorType; +import com.yahoo.api.annotations.Beta; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** +* A text generator based on language models (LLMs). By configuring a + * sentencepience tokenizer and models for encoding and decoding, this + * component generates text based on the given prompt. + * + * See llm.generator.def for configurable parameters. + * + * @author lesters + */ +@Beta +public class Generator extends AbstractComponent { + + private final static int TOKEN_EOS = 1; // end of sequence + + private final static String BATCH_DIMENSION = "d0"; + private final static String SEQUENCE_DIMENSION = "d1"; + + private final int tokenizerMaxTokens; + private final String encoderInputIdsName; + private final String encoderAttentionMaskName; + private final String encoderOutputName; + private final String decoderInputIdsName; + private final String decoderAttentionMaskName; + private final String decoderEncoderHiddenStateName; + private final String decoderOutputName; + + private final SentencePieceEmbedder tokenizer; + private final OnnxEvaluator encoder; + private final OnnxEvaluator decoder; + + @Inject + public Generator(OnnxRuntime onnx, GeneratorConfig config) { + // Set up tokenizer + tokenizer = new SentencePieceEmbedder.Builder(config.tokenizerModel().toString()).build(); + tokenizerMaxTokens = config.tokenizerMaxTokens(); + + // Set up encoder + encoderInputIdsName = config.encoderModelInputIdsName(); + encoderAttentionMaskName = config.encoderModelAttentionMaskName(); + encoderOutputName = config.encoderModelOutputName(); + + OnnxEvaluatorOptions encoderOptions = new OnnxEvaluatorOptions(); + encoderOptions.setExecutionMode(config.encoderOnnxExecutionMode().toString()); + encoderOptions.setInterOpThreads(modifyThreadCount(config.encoderOnnxInterOpThreads())); + encoderOptions.setIntraOpThreads(modifyThreadCount(config.encoderOnnxIntraOpThreads())); + + encoder = onnx.evaluatorOf(config.encoderModel().toString(), encoderOptions); + + // Set up decoder + decoderInputIdsName = config.decoderModelInputIdsName(); + decoderAttentionMaskName = config.decoderModelAttentionMaskName(); + decoderEncoderHiddenStateName = config.decoderModelEncoderHiddenStateName(); + decoderOutputName = config.decoderModelOutputName(); + + OnnxEvaluatorOptions decoderOptions = new OnnxEvaluatorOptions(); + decoderOptions.setExecutionMode(config.decoderOnnxExecutionMode().toString()); + decoderOptions.setInterOpThreads(modifyThreadCount(config.decoderOnnxInterOpThreads())); + decoderOptions.setIntraOpThreads(modifyThreadCount(config.decoderOnnxIntraOpThreads())); + + decoder = onnx.evaluatorOf(config.decoderModel().toString(), decoderOptions); + + validateModels(); + } + + /** + * Generates text by evaluating an encoder model to encode the prompt, and + * repeatedly evaluating a decoding model to generate tokens until some + * stopping criteria has been met. + * + * @param prompt the prompt to generate text from + * @param options options for text generation + * @return a text generated from the prompt + */ + public String generate(String prompt, GeneratorOptions options) { + return switch (options.getSearchMethod()) { + case GREEDY -> generateGreedy(prompt, options); + default -> generateNotImplemented(options); + }; + } + + public String generate(String prompt) { + return generate(prompt, new GeneratorOptions()); + } + + @Override public void deconstruct() { encoder.close(); decoder.close(); } + + private String generateNotImplemented(GeneratorOptions options) { + throw new UnsupportedOperationException("Search method '" + options.getSearchMethod() + "' is currently not implemented"); + } + + private String generateGreedy(String prompt, GeneratorOptions options) { + var generatedTokens = new ArrayList(); + generatedTokens.add(0); // Or target tokens + + // Tokenize + var inputTokens = tokenize(prompt); // Or source tokens + + // Evaluate encoder + var encoderInput = createTensorRepresentation(inputTokens, SEQUENCE_DIMENSION); + var encoderMask = createAttentionMask(encoderInput).expand(BATCH_DIMENSION); + var encoderOutput = evaluateEncoder(encoderInput.expand(BATCH_DIMENSION), encoderMask); + + // Greedy search just grabs the next most probable token + while (generatedTokens.size() < options.getMaxLength()) { // Todo: add stopping criteria + var decoderInput = createTensorRepresentation(generatedTokens, SEQUENCE_DIMENSION).expand(BATCH_DIMENSION); + var logits = evaluateDecoder(decoderInput, encoderMask, encoderOutput); + var nextToken = findMostProbableToken(logits, generatedTokens.size()-1, BATCH_DIMENSION, SEQUENCE_DIMENSION); + generatedTokens.add(nextToken); + } + + return detokenize(generatedTokens); + } + + private Tensor evaluateEncoder(Tensor input, Tensor mask) { + var encoderInputs = Map.of(encoderInputIdsName, input, + encoderAttentionMaskName, mask); + return encoder.evaluate(encoderInputs, encoderOutputName); + } + + private IndexedTensor evaluateDecoder(Tensor input, Tensor encoderMask, Tensor encoderOutput) { + var inputs = Map.of(decoderInputIdsName, input, + decoderAttentionMaskName, encoderMask, // yes, encoder's attention mask + decoderEncoderHiddenStateName, encoderOutput); + var output = decoder.evaluate(inputs, decoderOutputName); + if ( ! (output instanceof IndexedTensor indexedTensor)) { + throw new IllegalArgumentException("Output of decoder model is not an 'IndexedTensor'"); + } + return indexedTensor; + } + + /** + * Given a tensor 'logits' with 3 dimensions: batch, sequence, and vocabulary + * find the value in the vocabulary dimension with highest score for the given + * token in the sequence + */ + private static int findMostProbableToken(IndexedTensor logits, int seqIndex, String batchDim, String seqDim) { + if (logits.type().rank() != 3) { + throw new IllegalArgumentException("Expected a tensor with rank 3: batch, sequence, and vocabulary size. " + + "Got: " + logits.type()); + } + var iterator = logits.cellIterator(new PartialAddress.Builder(2). + add(batchDim, 0). + add(seqDim, seqIndex).build(), + DimensionSizes.of(logits.type())); + var maxVal = iterator.next().getValue(); + int maxIndex = 0; + for (int i = 1; iterator.hasNext(); ++i) { + var val = iterator.next().getValue(); + if (val >= maxVal && i != TOKEN_EOS) { + maxVal = val; + maxIndex = i; + } + } + return maxIndex; + } + + private List tokenize(String text) { + var tokens = tokenizer.embed(text, new Embedder.Context("tokenizer")); + tokens = tokens.size() >= tokenizerMaxTokens ? tokens.subList(0,tokenizerMaxTokens-1): tokens; + tokens.add(TOKEN_EOS); + return tokens; + } + + private String detokenize(List tokens) { + return tokenizer.decode(tokens, new Embedder.Context("tokenizer"), true); + } + + private static Tensor createTensorRepresentation(List tokens, String dimension) { + var size = tokens.size(); + TensorType type = new TensorType.Builder(TensorType.Value.FLOAT).indexed(dimension, size).build(); + IndexedTensor.Builder builder = IndexedTensor.Builder.of(type); + for (int i = 0; i < size; ++i) { + builder.cell(tokens.get(i), i); + } + return builder.build(); + } + + private static Tensor createAttentionMask(Tensor d) { + return d.map((x) -> x > 0 ? 1:0); + } + + private void validateModels() { + Map inputs = encoder.getInputInfo(); + validateName(inputs, encoderInputIdsName, "input"); + validateName(inputs, encoderAttentionMaskName, "input"); + + Map outputs = encoder.getOutputInfo(); + validateName(outputs, encoderOutputName, "output"); + + inputs = decoder.getInputInfo(); + validateName(inputs, decoderInputIdsName, "input"); + validateName(inputs, decoderAttentionMaskName, "input"); + validateName(inputs, decoderEncoderHiddenStateName, "input"); + + outputs = decoder.getOutputInfo(); + validateName(outputs, decoderOutputName, "output"); + } + + private void validateName(Map types, String name, String type) { + if ( ! types.containsKey(name)) { + throw new IllegalArgumentException("Model does not contain required " + type + ": '" + name + "'. " + + "Model contains: " + String.join(",", types.keySet())); + } + } + + private int modifyThreadCount(int numThreads) { + if (numThreads >= 0) + return numThreads; + return Math.max(1, (int) Math.ceil(((double) Runtime.getRuntime().availableProcessors()) / (-1 * numThreads))); + } +} diff --git a/model-integration/src/main/java/ai/vespa/llm/generation/GeneratorOptions.java b/model-integration/src/main/java/ai/vespa/llm/generation/GeneratorOptions.java new file mode 100644 index 00000000000..79b466e5a74 --- /dev/null +++ b/model-integration/src/main/java/ai/vespa/llm/generation/GeneratorOptions.java @@ -0,0 +1,37 @@ +package ai.vespa.llm.generation; + +import com.yahoo.api.annotations.Beta; + +@Beta +public class GeneratorOptions { + + public enum SearchMethod { + GREEDY, + CONTRASTIVE, + BEAM, + SAMPLE, + } + + private SearchMethod searchMethod = SearchMethod.GREEDY; + private int maxLength = 20; + + public SearchMethod getSearchMethod() { + return searchMethod; + } + + public GeneratorOptions setSearchMethod(SearchMethod searchMethod) { + this.searchMethod = searchMethod; + return this; + } + + public int getMaxLength() { + return maxLength; + } + + public GeneratorOptions setMaxLength(int maxLength) { + this.maxLength = maxLength; + return this; + } + + +} diff --git a/model-integration/src/main/java/ai/vespa/llm/generation/package-info.java b/model-integration/src/main/java/ai/vespa/llm/generation/package-info.java new file mode 100644 index 00000000000..ed3adb2f59e --- /dev/null +++ b/model-integration/src/main/java/ai/vespa/llm/generation/package-info.java @@ -0,0 +1,11 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +@PublicApi +package ai.vespa.llm.generation; + +import com.yahoo.api.annotations.PublicApi; +import com.yahoo.osgi.annotation.ExportPackage; + +/** + * API for generating text with language models. + */ \ No newline at end of file diff --git a/model-integration/src/main/java/ai/vespa/llm/package-info.java b/model-integration/src/main/java/ai/vespa/llm/package-info.java deleted file mode 100644 index 04fc24c51ee..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -@ExportPackage -@PublicApi -package ai.vespa.llm; - -import com.yahoo.api.annotations.PublicApi; -import com.yahoo.osgi.annotation.ExportPackage; - -/** - * API for working with large language models. - */ \ No newline at end of file diff --git a/model-integration/src/main/java/ai/vespa/llm/test/MockLanguageModel.java b/model-integration/src/main/java/ai/vespa/llm/test/MockLanguageModel.java deleted file mode 100644 index 54b085a451c..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/test/MockLanguageModel.java +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package ai.vespa.llm.test; - -import ai.vespa.llm.Completion; -import ai.vespa.llm.LanguageModel; -import ai.vespa.llm.Prompt; -import com.yahoo.api.annotations.Beta; - -import java.util.List; -import java.util.function.Function; - -/** - * @author bratseth - */ -@Beta -public class MockLanguageModel implements LanguageModel { - - private final Function> completer; - - public MockLanguageModel(Builder builder) { - completer = builder.completer; - } - - @Override - public List complete(Prompt prompt) { - return completer.apply(prompt); - } - - public static class Builder { - - private Function> completer = prompt -> List.of(Completion.from("")); - - public Builder completer(Function> completer) { - this.completer = completer; - return this; - } - - public Builder() {} - - public MockLanguageModel build() { return new MockLanguageModel(this); } - - } - -} diff --git a/model-integration/src/main/java/ai/vespa/llm/test/package-info.java b/model-integration/src/main/java/ai/vespa/llm/test/package-info.java deleted file mode 100644 index 0d51815fd6d..00000000000 --- a/model-integration/src/main/java/ai/vespa/llm/test/package-info.java +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -@ExportPackage -@PublicApi -package ai.vespa.llm.test; - -/** - * Tools for writing tests when working with large language models. - */ - -import com.yahoo.api.annotations.PublicApi; -import com.yahoo.osgi.annotation.ExportPackage; \ No newline at end of file diff --git a/model-integration/src/test/java/ai/vespa/llm/CompletionTest.java b/model-integration/src/test/java/ai/vespa/llm/CompletionTest.java deleted file mode 100644 index 30b1c8c2fb1..00000000000 --- a/model-integration/src/test/java/ai/vespa/llm/CompletionTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package ai.vespa.llm; - -import ai.vespa.llm.test.MockLanguageModel; -import org.junit.jupiter.api.Test; - -import java.util.List; -import java.util.function.Function; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * Tests completion with a mock completer. - * - * @author bratseth - */ -public class CompletionTest { - - @Test - public void testCompletion() { - Function> completer = in -> - switch (in.asString()) { - case "Complete this: " -> List.of(Completion.from("The completion")); - default -> throw new RuntimeException("Cannot complete '" + in + "'"); - }; - var llm = new MockLanguageModel.Builder().completer(completer).build(); - - String input = "Complete this: "; - StringPrompt prompt = StringPrompt.from(input); - for (int i = 0; i < 10; i++) { - var completion = llm.complete(prompt).get(0); - prompt = prompt.append(completion); - if (completion.finishReason() == Completion.FinishReason.stop) break; - } - assertEquals("Complete this: The completion", prompt.asString()); - } - -} diff --git a/model-integration/src/test/java/ai/vespa/llm/GeneratorTest.java b/model-integration/src/test/java/ai/vespa/llm/GeneratorTest.java deleted file mode 100644 index c22902b344f..00000000000 --- a/model-integration/src/test/java/ai/vespa/llm/GeneratorTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package ai.vespa.llm; - -import ai.vespa.modelintegration.evaluator.OnnxRuntime; -import com.yahoo.config.ModelReference; -import com.yahoo.llm.GeneratorConfig; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assume.assumeTrue; - -public class GeneratorTest { - - @Test - public void testGenerator() { - String vocabPath = "src/test/models/onnx/llm/en.wiki.bpe.vs10000.model"; - String encoderModelPath = "src/test/models/onnx/llm/random_encoder.onnx"; - String decoderModelPath = "src/test/models/onnx/llm/random_decoder.onnx"; - assumeTrue(OnnxRuntime.isRuntimeAvailable(encoderModelPath)); - - GeneratorConfig.Builder builder = new GeneratorConfig.Builder(); - builder.tokenizerModel(ModelReference.valueOf(vocabPath)); - builder.encoderModel(ModelReference.valueOf(encoderModelPath)); - builder.decoderModel(ModelReference.valueOf(decoderModelPath)); - Generator generator = newGenerator(builder.build()); - - GeneratorOptions options = new GeneratorOptions(); - options.setSearchMethod(GeneratorOptions.SearchMethod.GREEDY); - options.setMaxLength(10); - - String prompt = "generate some random text"; - String result = generator.generate(prompt, options); - - assertEquals(" linear recruit latest sack annually institutions cert solid references", result); - } - - private static Generator newGenerator(GeneratorConfig cfg) { - return new Generator(new OnnxRuntime(), cfg); - } - -} diff --git a/model-integration/src/test/java/ai/vespa/llm/generation/GeneratorTest.java b/model-integration/src/test/java/ai/vespa/llm/generation/GeneratorTest.java new file mode 100644 index 00000000000..8c9b961f4a8 --- /dev/null +++ b/model-integration/src/test/java/ai/vespa/llm/generation/GeneratorTest.java @@ -0,0 +1,42 @@ +package ai.vespa.llm.generation; + +import ai.vespa.llm.generation.Generator; +import ai.vespa.llm.generation.GeneratorOptions; +import ai.vespa.modelintegration.evaluator.OnnxRuntime; +import com.yahoo.config.ModelReference; +import com.yahoo.llm.GeneratorConfig; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assume.assumeTrue; + +public class GeneratorTest { + + @Test + public void testGenerator() { + String vocabPath = "src/test/models/onnx/llm/en.wiki.bpe.vs10000.model"; + String encoderModelPath = "src/test/models/onnx/llm/random_encoder.onnx"; + String decoderModelPath = "src/test/models/onnx/llm/random_decoder.onnx"; + assumeTrue(OnnxRuntime.isRuntimeAvailable(encoderModelPath)); + + GeneratorConfig.Builder builder = new GeneratorConfig.Builder(); + builder.tokenizerModel(ModelReference.valueOf(vocabPath)); + builder.encoderModel(ModelReference.valueOf(encoderModelPath)); + builder.decoderModel(ModelReference.valueOf(decoderModelPath)); + Generator generator = newGenerator(builder.build()); + + GeneratorOptions options = new GeneratorOptions(); + options.setSearchMethod(GeneratorOptions.SearchMethod.GREEDY); + options.setMaxLength(10); + + String prompt = "generate some random text"; + String result = generator.generate(prompt, options); + + assertEquals(" linear recruit latest sack annually institutions cert solid references", result); + } + + private static Generator newGenerator(GeneratorConfig cfg) { + return new Generator(new OnnxRuntime(), cfg); + } + +} diff --git a/openai-client/abi-spec.json b/openai-client/abi-spec.json new file mode 100644 index 00000000000..039ca57fc64 --- /dev/null +++ b/openai-client/abi-spec.json @@ -0,0 +1,29 @@ +{ + "ai.vespa.llm.client.openai.OpenAiClient$Builder" : { + "superClass" : "java.lang.Object", + "interfaces" : [ ], + "attributes" : [ + "public" + ], + "methods" : [ + "public void (java.lang.String)", + "public ai.vespa.llm.client.openai.OpenAiClient$Builder model(java.lang.String)", + "public ai.vespa.llm.client.openai.OpenAiClient$Builder echo(boolean)", + "public ai.vespa.llm.client.openai.OpenAiClient build()" + ], + "fields" : [ ] + }, + "ai.vespa.llm.client.openai.OpenAiClient" : { + "superClass" : "java.lang.Object", + "interfaces" : [ + "ai.vespa.llm.LanguageModel" + ], + "attributes" : [ + "public" + ], + "methods" : [ + "public java.util.List complete(ai.vespa.llm.completion.Prompt)" + ], + "fields" : [ ] + } +} \ No newline at end of file diff --git a/openai-client/pom.xml b/openai-client/pom.xml new file mode 100644 index 00000000000..f4362194b58 --- /dev/null +++ b/openai-client/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.yahoo.vespa + parent + 8-SNAPSHOT + ../parent/pom.xml + + openai-client + container-plugin + 8-SNAPSHOT + + + 0.12.0 + + + + + com.theokanning.openai-gpt3-java + service + ${openai-gpt3.version} + + + com.yahoo.vespa + annotations + ${project.version} + provided + + + com.yahoo.vespa + vespajlib + ${project.version} + provided + + + + + + + com.yahoo.vespa + bundle-plugin + true + + + org.apache.maven.plugins + maven-compiler-plugin + + + + -Xlint:all + -Xlint:-rawtypes + -Xlint:-unchecked + -Xlint:-serial + + + + + com.yahoo.vespa + abi-check-plugin + + + + + \ No newline at end of file diff --git a/openai-client/src/main/java/ai/vespa/llm/client/openai/OpenAiClient.java b/openai-client/src/main/java/ai/vespa/llm/client/openai/OpenAiClient.java new file mode 100644 index 00000000000..66be5ff1f69 --- /dev/null +++ b/openai-client/src/main/java/ai/vespa/llm/client/openai/OpenAiClient.java @@ -0,0 +1,84 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package ai.vespa.llm.client.openai; + +import ai.vespa.llm.completion.Completion; +import ai.vespa.llm.LanguageModel; +import ai.vespa.llm.completion.Prompt; +import com.theokanning.openai.OpenAiHttpException; +import com.theokanning.openai.completion.CompletionRequest; +import com.theokanning.openai.service.OpenAiService; +import com.yahoo.api.annotations.Beta; +import com.yahoo.yolean.Exceptions; + +import java.util.List; + +/** + * A client to the OpenAI language model API. Refer to https://platform.openai.com/docs/api-reference/. + * + * @author bratseth + */ +@Beta +public class OpenAiClient implements LanguageModel { + + private final OpenAiService openAiService; + private final String model; + private final boolean echo; + + private OpenAiClient(Builder builder) { + openAiService = new OpenAiService(builder.token); + this.model = builder.model; + this.echo = builder.echo; + } + + @Override + public List complete(Prompt prompt) { + try { + CompletionRequest completionRequest = CompletionRequest.builder() + .prompt(prompt.asString()) + .model(model) + .echo(echo) + .build(); + return openAiService.createCompletion(completionRequest).getChoices().stream() + .map(c -> new Completion(c.getText(), toFinishReason(c.getFinish_reason()))).toList(); + } + catch (OpenAiHttpException e) { + throw new RuntimeException(Exceptions.toMessageString(e)); + } + } + + private Completion.FinishReason toFinishReason(String finishReasonString) { + return switch(finishReasonString) { + case "length" -> Completion.FinishReason.length; + case "stop" -> Completion.FinishReason.stop; + default -> throw new IllegalStateException("Unknown OpenAi completion finish reason '" + finishReasonString + "'"); + }; + } + + public static class Builder { + + private final String token; + private String model = "text-davinci-003"; + private boolean echo = false; + + public Builder(String token) { + this.token = token; + } + + /** One of the language models listed at https://platform.openai.com/docs/models */ + public Builder model(String model) { + this.model = model; + return this; + } + + public Builder echo(boolean echo) { + this.echo = echo; + return this; + } + + public OpenAiClient build() { + return new OpenAiClient(this); + } + + } + +} diff --git a/openai-client/src/main/java/ai/vespa/llm/client/openai/package-info.java b/openai-client/src/main/java/ai/vespa/llm/client/openai/package-info.java new file mode 100644 index 00000000000..8b8b99308b0 --- /dev/null +++ b/openai-client/src/main/java/ai/vespa/llm/client/openai/package-info.java @@ -0,0 +1,11 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +@PublicApi +package ai.vespa.llm.client.openai; + +import com.yahoo.api.annotations.PublicApi; +import com.yahoo.osgi.annotation.ExportPackage; + +/** + * Client to OpenAi's large language models. + */ \ No newline at end of file diff --git a/parent/pom.xml b/parent/pom.xml index f3b9fc9baeb..6b84137b43b 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -565,17 +565,6 @@ onnxruntime ${onnxruntime.version} - - com.theokanning.openai-gpt3-java - service - ${openai-gpt3.version} - - - com.fasterxml.jackson.core - jackson-databind - - - com.yahoo.athenz athenz-cert-refresher @@ -1183,7 +1172,6 @@ 4.1.86.Final 2.0.54.Final 1.13.1 - 0.12.0 20230227 1.8.0 0.6.0 diff --git a/pom.xml b/pom.xml index c4b6e200e2e..a601e847e2b 100644 --- a/pom.xml +++ b/pom.xml @@ -91,7 +91,6 @@ jdisc_core_test jrt linguistics - opennlp-linguistics linguistics-components logd logserver @@ -102,6 +101,8 @@ model-integration node-repository node-admin + openai-client + opennlp-linguistics orchestrator-restapi orchestrator parent diff --git a/vespajlib/abi-spec.json b/vespajlib/abi-spec.json index 48d519b3a62..fe07460c20b 100644 --- a/vespajlib/abi-spec.json +++ b/vespajlib/abi-spec.json @@ -3995,5 +3995,113 @@ "public void leaving(com.yahoo.yolean.trace.TraceNode)" ], "fields" : [ ] + }, + "ai.vespa.llm.LanguageModel" : { + "superClass" : "java.lang.Object", + "interfaces" : [ ], + "attributes" : [ + "public", + "interface", + "abstract" + ], + "methods" : [ + "public abstract java.util.List complete(ai.vespa.llm.completion.Prompt)" + ], + "fields" : [ ] + }, + "ai.vespa.llm.completion.Completion$FinishReason" : { + "superClass" : "java.lang.Enum", + "interfaces" : [ ], + "attributes" : [ + "public", + "final", + "enum" + ], + "methods" : [ + "public static ai.vespa.llm.completion.Completion$FinishReason[] values()", + "public static ai.vespa.llm.completion.Completion$FinishReason valueOf(java.lang.String)" + ], + "fields" : [ + "public static final enum ai.vespa.llm.completion.Completion$FinishReason length", + "public static final enum ai.vespa.llm.completion.Completion$FinishReason stop" + ] + }, + "ai.vespa.llm.completion.Completion" : { + "superClass" : "java.lang.Record", + "interfaces" : [ ], + "attributes" : [ + "public", + "final", + "record" + ], + "methods" : [ + "public void (java.lang.String, ai.vespa.llm.completion.Completion$FinishReason)", + "public java.lang.String text()", + "public ai.vespa.llm.completion.Completion$FinishReason finishReason()", + "public static ai.vespa.llm.completion.Completion from(java.lang.String)", + "public final java.lang.String toString()", + "public final int hashCode()", + "public final boolean equals(java.lang.Object)" + ], + "fields" : [ ] + }, + "ai.vespa.llm.completion.Prompt" : { + "superClass" : "java.lang.Object", + "interfaces" : [ ], + "attributes" : [ + "public", + "abstract" + ], + "methods" : [ + "public void ()", + "public abstract java.lang.String asString()", + "public ai.vespa.llm.completion.Prompt append(ai.vespa.llm.completion.Completion)", + "public abstract ai.vespa.llm.completion.Prompt append(java.lang.String)" + ], + "fields" : [ ] + }, + "ai.vespa.llm.completion.StringPrompt" : { + "superClass" : "ai.vespa.llm.completion.Prompt", + "interfaces" : [ ], + "attributes" : [ + "public" + ], + "methods" : [ + "public java.lang.String asString()", + "public ai.vespa.llm.completion.StringPrompt append(java.lang.String)", + "public ai.vespa.llm.completion.StringPrompt append(ai.vespa.llm.completion.Completion)", + "public java.lang.String toString()", + "public static ai.vespa.llm.completion.StringPrompt from(java.lang.String)", + "public bridge synthetic ai.vespa.llm.completion.Prompt append(java.lang.String)", + "public bridge synthetic ai.vespa.llm.completion.Prompt append(ai.vespa.llm.completion.Completion)" + ], + "fields" : [ ] + }, + "ai.vespa.llm.test.MockLanguageModel$Builder" : { + "superClass" : "java.lang.Object", + "interfaces" : [ ], + "attributes" : [ + "public" + ], + "methods" : [ + "public ai.vespa.llm.test.MockLanguageModel$Builder completer(java.util.function.Function)", + "public void ()", + "public ai.vespa.llm.test.MockLanguageModel build()" + ], + "fields" : [ ] + }, + "ai.vespa.llm.test.MockLanguageModel" : { + "superClass" : "java.lang.Object", + "interfaces" : [ + "ai.vespa.llm.LanguageModel" + ], + "attributes" : [ + "public" + ], + "methods" : [ + "public void (ai.vespa.llm.test.MockLanguageModel$Builder)", + "public java.util.List complete(ai.vespa.llm.completion.Prompt)" + ], + "fields" : [ ] } } \ No newline at end of file diff --git a/vespajlib/src/main/java/ai/vespa/llm/LanguageModel.java b/vespajlib/src/main/java/ai/vespa/llm/LanguageModel.java new file mode 100644 index 00000000000..829b74f7bf4 --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/LanguageModel.java @@ -0,0 +1,20 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package ai.vespa.llm; + +import ai.vespa.llm.completion.Completion; +import ai.vespa.llm.completion.Prompt; +import com.yahoo.api.annotations.Beta; + +import java.util.List; + +/** + * Interface to language models. + * + * @author bratseth + */ +@Beta +public interface LanguageModel { + + List complete(Prompt prompt); + +} diff --git a/vespajlib/src/main/java/ai/vespa/llm/completion/Completion.java b/vespajlib/src/main/java/ai/vespa/llm/completion/Completion.java new file mode 100644 index 00000000000..30645b5151f --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/completion/Completion.java @@ -0,0 +1,41 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package ai.vespa.llm.completion; + +import com.yahoo.api.annotations.Beta; + +import java.util.Objects; + +/** + * A completion from a language model. + * + * @author bratseth + */ +@Beta +public record Completion(String text, FinishReason finishReason) { + + public enum FinishReason { + + /** The maximum length of a completion was reached. */ + length, + + /** The completion is the predicted ending of the prompt. */ + stop + + } + + public Completion(String text, FinishReason finishReason) { + this.text = Objects.requireNonNull(text); + this.finishReason = Objects.requireNonNull(finishReason); + } + + /** Returns the generated text completion. */ + public String text() { return text; } + + /** Returns the reason this completion ended. */ + public FinishReason finishReason() { return finishReason; } + + public static Completion from(String text) { + return new Completion(text, FinishReason.stop); + } + +} diff --git a/vespajlib/src/main/java/ai/vespa/llm/completion/Prompt.java b/vespajlib/src/main/java/ai/vespa/llm/completion/Prompt.java new file mode 100644 index 00000000000..d5d0247d6b0 --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/completion/Prompt.java @@ -0,0 +1,23 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package ai.vespa.llm.completion; + +import com.yahoo.api.annotations.Beta; + +/** + * A prompt that can be given to a large language model to generate a completion. + * + * @author bratseth + */ +@Beta +public abstract class Prompt { + + public abstract String asString(); + + /** Returns a new prompt with the text of the given completion appended. */ + public Prompt append(Completion completion) { + return append(completion.text()); + } + + public abstract Prompt append(String text); + +} diff --git a/vespajlib/src/main/java/ai/vespa/llm/completion/StringPrompt.java b/vespajlib/src/main/java/ai/vespa/llm/completion/StringPrompt.java new file mode 100644 index 00000000000..e8392ca992e --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/completion/StringPrompt.java @@ -0,0 +1,43 @@ +package ai.vespa.llm.completion; + +import com.yahoo.api.annotations.Beta; + +import java.util.Objects; + +/** + * A prompt which just consists of a string. + * + * @author bratseth + */ +@Beta +public class StringPrompt extends Prompt { + + private final String string; + + private StringPrompt(String string) { + this.string = Objects.requireNonNull(string); + } + + @Override + public String asString() { return string; } + + @Override + public StringPrompt append(String text) { + return StringPrompt.from(string + text); + } + + @Override + public StringPrompt append(Completion completion) { + return append(completion.text()); + } + + @Override + public String toString() { + return string; + } + + public static StringPrompt from(String string) { + return new StringPrompt(string); + } + +} diff --git a/vespajlib/src/main/java/ai/vespa/llm/completion/package-info.java b/vespajlib/src/main/java/ai/vespa/llm/completion/package-info.java new file mode 100644 index 00000000000..79898c694ca --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/completion/package-info.java @@ -0,0 +1,11 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +@PublicApi +package ai.vespa.llm.completion; + +import com.yahoo.api.annotations.PublicApi; +import com.yahoo.osgi.annotation.ExportPackage; + +/** + * Classes for generating text completions with language models. + */ \ No newline at end of file diff --git a/vespajlib/src/main/java/ai/vespa/llm/package-info.java b/vespajlib/src/main/java/ai/vespa/llm/package-info.java new file mode 100644 index 00000000000..04fc24c51ee --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/package-info.java @@ -0,0 +1,11 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +@PublicApi +package ai.vespa.llm; + +import com.yahoo.api.annotations.PublicApi; +import com.yahoo.osgi.annotation.ExportPackage; + +/** + * API for working with large language models. + */ \ No newline at end of file diff --git a/vespajlib/src/main/java/ai/vespa/llm/test/MockLanguageModel.java b/vespajlib/src/main/java/ai/vespa/llm/test/MockLanguageModel.java new file mode 100644 index 00000000000..d47f43c55b2 --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/test/MockLanguageModel.java @@ -0,0 +1,44 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package ai.vespa.llm.test; + +import ai.vespa.llm.LanguageModel; +import ai.vespa.llm.completion.Completion; +import ai.vespa.llm.completion.Prompt; +import com.yahoo.api.annotations.Beta; + +import java.util.List; +import java.util.function.Function; + +/** + * @author bratseth + */ +@Beta +public class MockLanguageModel implements LanguageModel { + + private final Function> completer; + + public MockLanguageModel(Builder builder) { + completer = builder.completer; + } + + @Override + public List complete(Prompt prompt) { + return completer.apply(prompt); + } + + public static class Builder { + + private Function> completer = prompt -> List.of(Completion.from("")); + + public Builder completer(Function> completer) { + this.completer = completer; + return this; + } + + public Builder() {} + + public MockLanguageModel build() { return new MockLanguageModel(this); } + + } + +} diff --git a/vespajlib/src/main/java/ai/vespa/llm/test/package-info.java b/vespajlib/src/main/java/ai/vespa/llm/test/package-info.java new file mode 100644 index 00000000000..0d51815fd6d --- /dev/null +++ b/vespajlib/src/main/java/ai/vespa/llm/test/package-info.java @@ -0,0 +1,11 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +@ExportPackage +@PublicApi +package ai.vespa.llm.test; + +/** + * Tools for writing tests when working with large language models. + */ + +import com.yahoo.api.annotations.PublicApi; +import com.yahoo.osgi.annotation.ExportPackage; \ No newline at end of file diff --git a/vespajlib/src/test/java/ai/vespa/llm/completion/CompletionTest.java b/vespajlib/src/test/java/ai/vespa/llm/completion/CompletionTest.java new file mode 100644 index 00000000000..1c794c64d1a --- /dev/null +++ b/vespajlib/src/test/java/ai/vespa/llm/completion/CompletionTest.java @@ -0,0 +1,40 @@ +package ai.vespa.llm.completion; + +import ai.vespa.llm.completion.Completion; +import ai.vespa.llm.completion.Prompt; +import ai.vespa.llm.completion.StringPrompt; +import ai.vespa.llm.test.MockLanguageModel; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.function.Function; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Tests completion with a mock completer. + * + * @author bratseth + */ +public class CompletionTest { + + @Test + public void testCompletion() { + Function> completer = in -> + switch (in.asString()) { + case "Complete this: " -> List.of(Completion.from("The completion")); + default -> throw new RuntimeException("Cannot complete '" + in + "'"); + }; + var llm = new MockLanguageModel.Builder().completer(completer).build(); + + String input = "Complete this: "; + StringPrompt prompt = StringPrompt.from(input); + for (int i = 0; i < 10; i++) { + var completion = llm.complete(prompt).get(0); + prompt = prompt.append(completion); + if (completion.finishReason() == Completion.FinishReason.stop) break; + } + assertEquals("Complete this: The completion", prompt.asString()); + } + +} -- cgit v1.2.3 From 901f992bf024fe1b994385ca76b7b59fe2d8a78f Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Tue, 25 Apr 2023 21:43:59 +0200 Subject: Don't care about com.sun.jna --- jdisc_core/src/test/java/com/yahoo/jdisc/core/ExportPackagesIT.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/jdisc_core/src/test/java/com/yahoo/jdisc/core/ExportPackagesIT.java b/jdisc_core/src/test/java/com/yahoo/jdisc/core/ExportPackagesIT.java index 7ec3406be1f..a2aade05059 100644 --- a/jdisc_core/src/test/java/com/yahoo/jdisc/core/ExportPackagesIT.java +++ b/jdisc_core/src/test/java/com/yahoo/jdisc/core/ExportPackagesIT.java @@ -78,7 +78,10 @@ public class ExportPackagesIT { } private static Set removeNewPackageOnJava20(Set packages) { - return packages.stream().filter(p -> ! p.contains("java.lang.foreign")).collect(Collectors.toSet()); + return packages.stream() + .filter(p -> ! p.contains("java.lang.foreign")) + .filter(p -> ! p.contains("com.sun.jna")) + .collect(Collectors.toSet()); } private static StringBuilder getDiff(Set actual, Set expected) { -- cgit v1.2.3