Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
</dependency>
<dependency>
<groupId>com.github.luben</groupId>
<artifactId>zstd-jni</artifactId>
Expand Down
31 changes: 31 additions & 0 deletions src/main/java/net/ravendb/client/documents/AI/AiAnswer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package net.ravendb.client.documents.AI;

public class AiAnswer<TAnswer> {
private TAnswer answer;
private AiConversationResult status;

public AiAnswer() {
}

public AiAnswer(TAnswer answer, AiConversationResult status) {
this.answer = answer;
this.status = status;
}

public TAnswer getAnswer() {
return answer;
}

public void setAnswer(TAnswer answer) {
this.answer = answer;
}

public AiConversationResult getStatus() {
return status;
}

public void setStatus(AiConversationResult status) {
this.status = status;
}
}

366 changes: 366 additions & 0 deletions src/main/java/net/ravendb/client/documents/AI/AiConversation.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package net.ravendb.client.documents.AI;

import java.util.HashMap;
import java.util.Map;

public class AiConversationCreationOptions {
private Map<String, Object> parameters;
private Integer expirationInSec;

public AiConversationCreationOptions() {
}

public AiConversationCreationOptions(Map<String, Object> parameters) {
this(parameters, null);
}

public AiConversationCreationOptions(Map<String, Object> parameters, Integer expirationInSec) {
this.parameters = parameters;
this.expirationInSec = expirationInSec;
}

public Map<String, Object> getParameters() {
return parameters;
}

public void setParameters(Map<String, Object> parameters) {
this.parameters = parameters;
}

public AiConversationCreationOptions addParameter(String name, Object value) {
if (this.parameters == null) {
this.parameters = new HashMap<>();
}
this.parameters.put(name, value);
return this;
}

public Integer getExpirationInSec() {
return expirationInSec;
}

public void setExpirationInSec(Integer expirationInSec) {
this.expirationInSec = expirationInSec;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.ravendb.client.documents.AI;

public enum AiConversationResult {
Done,
ActionRequired
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package net.ravendb.client.documents.AI;

public enum AiHandleErrorStrategy {
SendErrorsToModel,
RaiseImmediately
}
6 changes: 6 additions & 0 deletions src/main/java/net/ravendb/client/documents/AI/AiHandler.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package net.ravendb.client.documents.AI;

@FunctionalInterface
public interface AiHandler<TArgs> {
Object invoke(TArgs args);
}
14 changes: 14 additions & 0 deletions src/main/java/net/ravendb/client/documents/AI/AiMessagePrompt.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package net.ravendb.client.documents.AI;

public class AiMessagePrompt {
class AiMessagePromptFields {
public static final String TEXT = "text";
public static final String TYPE = "type";
private AiMessagePromptFields() {}
}

class AiMessagePromptTypes {
public static final String TEXT = "text";
private AiMessagePromptTypes() {}
}
}
99 changes: 99 additions & 0 deletions src/main/java/net/ravendb/client/documents/AI/AiOperations.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package net.ravendb.client.documents.AI;

import net.ravendb.client.documents.IDocumentStore;
import net.ravendb.client.documents.operations.AI.agents.*;
import net.ravendb.client.documents.operations.AI.agents.AiAgentConfiguration;
import net.ravendb.client.documents.operations.MaintenanceOperationExecutor;

public class AiOperations {
private final IDocumentStore store;
private final String databaseName;
private final MaintenanceOperationExecutor executor;

/**
* Initializes a new instance of AiOperations for a given document store and optional database name.
*/
public AiOperations(IDocumentStore store, String databaseName) {
this.store = store;
this.databaseName = databaseName;
this.executor = this.store.maintenance().forDatabase(this.databaseName);
}

public AiOperations(IDocumentStore store) {
this.store = store;
this.databaseName = store.getDatabase();
this.executor = this.store.maintenance().forDatabase(this.databaseName);
}

/**
* Returns an AiOperations instance for a different database.
*/
public AiOperations forDatabase(String databaseName) {
if (this.databaseName.equalsIgnoreCase(databaseName)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.databaseName can be NULL , if t will be you will get an exception
please do a nullity check before comparing it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return this;
}
return new AiOperations(this.store, databaseName);
}

/**
* Creates or updates an AI agent configuration (with the given schema) on the database.
*/
public <TSchema> AiAgentConfigurationResult createAgent(
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In C# we have

public AiAgentConfigurationResult CreateAgent(AiAgentConfiguration configuration)

as well

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

AiAgentConfiguration configuration,
TSchema sampleObject) {
AddOrUpdateAiAgentOperation operation = new AddOrUpdateAiAgentOperation(configuration, sampleObject);
return executor.send(operation);
}

/**
* Creates or updates an AI agent configuration (without given schema) on the database.
*/
public <TSchema> AiAgentConfigurationResult createAgent(AiAgentConfiguration configuration) {
AddOrUpdateAiAgentOperation operation = new AddOrUpdateAiAgentOperation(configuration);
return executor.send(operation);
}

/**
* Retrieves the AI agent configuration for a specific agent.
*/
public AiAgentConfiguration getAgent(String agentId) {
GetAiAgentsOperation operation = new GetAiAgentsOperation(agentId);
GetAiAgentsResponse response = executor.send(operation);
if (response.getAiAgents() != null && !response.getAiAgents().isEmpty()) {
return response.getAiAgents().get(0);
}
return null;
}

/**
* Retrieves all AI agents and their configurations.
*/
public GetAiAgentsResponse getAgents() {
GetAiAgentsOperation operation = new GetAiAgentsOperation();
return executor.send(operation);
}

/**
* Deletes an AI agent configuration.
*/
public AiAgentConfigurationResult deleteAgent(String identifier) {
DeleteAiAgentOperation operation = new DeleteAiAgentOperation(identifier);
return executor.send(operation);
}

/**
* Opens an AI conversation for an agent.
*/
public AiConversation conversation(String agentId, String conversationId, AiConversationCreationOptions creationOptions) {
return new AiConversation(store, databaseName, agentId, conversationId, creationOptions, null);
}

/**
* Opens an AI conversation for an agent.
*/
public AiConversation conversation(String agentId, String conversationId,
AiConversationCreationOptions creationOptions,
String changeVector) {
return new AiConversation(store, databaseName, agentId, conversationId, creationOptions, changeVector);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package net.ravendb.client.documents.AI;

import java.util.concurrent.CompletableFuture;

/**
* Callback invoked with each streamed chunk from the AI agent response.
* The callback can be synchronous or asynchronous.
*/
@FunctionalInterface
public interface AiStreamCallback {

/**
* Handle a streamed text chunk from the AI agent.
* Implementations may process this synchronously or asynchronously.
*
* @param chunk The streamed text chunk from the specified property.
*/
CompletableFuture<Void> onChunk(String chunk);
}
20 changes: 20 additions & 0 deletions src/main/java/net/ravendb/client/documents/AI/ContentPart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package net.ravendb.client.documents.AI;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.node.ObjectNode;

public abstract class ContentPart {

@JsonProperty("type")
private final String type;

protected ContentPart(String type) {
this.type = type;
}

public String getType() {
return type;
}

public abstract ObjectNode toJson();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package net.ravendb.client.documents.AI;

import com.fasterxml.jackson.core.JsonProcessingException;
import net.ravendb.client.documents.operations.AI.agents.AiAgentActionRequest;
import java.util.concurrent.CompletableFuture;

@FunctionalInterface
public interface IActionInvocation {
CompletableFuture<Void> invoke(AiAgentActionRequest request) throws JsonProcessingException;
}
33 changes: 33 additions & 0 deletions src/main/java/net/ravendb/client/documents/AI/TextPart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.ravendb.client.documents.AI;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;

public final class TextPart extends ContentPart {

@JsonProperty("text")
private String text;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should add the annotation @notblank(message = "text cannot be null or blank") if we want to make sure it won't be null or empty or just spaces

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


public TextPart(String text) {
super(AiMessagePrompt.AiMessagePromptTypes.TEXT);
this.text = text;
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

@Override
public ObjectNode toJson() {
ObjectNode json = JsonNodeFactory.instance.objectNode();
json.put(AiMessagePrompt.AiMessagePromptFields.TYPE, getType());
json.put(AiMessagePrompt.AiMessagePromptFields.TEXT, getText());
return json;
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.ravendb.client.documents.AI;

import net.ravendb.client.documents.operations.AI.agents.AiAgentActionRequest;

/**
* Event arguments for an unhandled action in an AI agent conversation.
*/
public class UnhandledActionEventArgs {

private AiConversation sender;
private AiAgentActionRequest action;

public UnhandledActionEventArgs(AiConversation sender, AiAgentActionRequest action) {
this.action = action;
this.sender = sender;
}

public AiConversation getSender() {
return sender;
}

public void setSender(AiConversation sender) {
this.sender = sender;
}

public AiAgentActionRequest getAction() {
return action;
}

public void setAction(AiAgentActionRequest action) {
this.action = action;
}
}
10 changes: 10 additions & 0 deletions src/main/java/net/ravendb/client/documents/DocumentStoreBase.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.ravendb.client.primitives.EventHandler;
import net.ravendb.client.primitives.EventHelper;
import net.ravendb.client.primitives.VoidArgs;
import net.ravendb.client.documents.AI.AiOperations;
import org.apache.commons.lang3.StringUtils;

import java.net.MalformedURLException;
Expand Down Expand Up @@ -146,6 +147,15 @@ public TimeSeriesOperations timeSeries() {
}

private DocumentConventions conventions;
private AiOperations aiOperations;

@Override
public AiOperations ai(){
if (this.aiOperations == null) {
this.aiOperations = new AiOperations(this);
}
return this.aiOperations;
}

/**
* Gets the conventions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.ravendb.client.documents.conventions.DocumentConventions;
import net.ravendb.client.documents.identity.IHiLoIdGenerator;
import net.ravendb.client.documents.indexes.IAbstractIndexCreationTask;
import net.ravendb.client.documents.AI.AiOperations;
import net.ravendb.client.documents.operations.MaintenanceOperationExecutor;
import net.ravendb.client.documents.operations.OperationExecutor;
import net.ravendb.client.documents.session.*;
Expand All @@ -28,6 +29,8 @@ public interface IDocumentStore extends IDisposalNotification {

KeyStore getCertificate();

AiOperations ai();

IHiLoIdGenerator getHiLoIdGenerator();

void addBeforeStoreListener(EventHandler<BeforeStoreEventArgs> handler);
Expand Down
Loading
Loading