Remove chain package. Fixes #109

This commit is contained in:
Mark Pollack
2023-12-12 15:42:37 -05:00
parent 8139af468e
commit a58e1fec64
9 changed files with 0 additions and 263 deletions

View File

@@ -232,31 +232,6 @@ Though the `DocumentWriter` interface isn't exclusively for Vector Database writ
They ascertain which document sections the AI should use for generating responses.
Examples of Vector Databases include Chroma, Postgres, Pinecone, Weaviate, Mongo Atlas, and Redis. Spring AI's `VectorStore` abstraction permits effortless transitions between database implementations.
### Chaining together multiple AI model interactions
**Chains:** Many AI solutions require multiple AI interactions to respond to a single user input.
"Chains" organize these interactions, offering modular AI workflows that promote reusability.
While you can create custom Chains tailored to your specific use case, pre-configured use-case-specific Chains are provided to accelerate your development.
Use cases such as Question-Answering, Text Generation, and Summarization are examples.
* This is currently a work in progress.
### Memory
**Memory:** To support multiple AI model interactions, your application must recall the previous inputs and outputs.
A variety of algorithms are available for different scenarios, often backed by databases like Redis, Cassandra, MongoDB, Postgres, and other database technologies.
* This is currently a work in progress
### Agents
Beyond Chains, Agents represent the next level of sophistication.
Agents use the AI models themselves to determine the techniques and steps to respond to a user's query.
Agents might even dynamically access external data sources to retrieve information necessary for responding to a user.
It's getting a bit funky, isn't it?
* This is currently a work in progress
## Building
To build with only unit tests

View File

@@ -1,69 +0,0 @@
package org.springframework.ai.chain;
import org.springframework.ai.memory.Memory;
import java.util.*;
public abstract class AbstractChain implements Chain {
private Optional<Memory> memory = Optional.empty();
public Optional<Memory> getMemory() {
return this.memory;
}
public void setMemory(Memory memory) {
Objects.requireNonNull(memory, "Memory can not be null.");
this.memory = Optional.of(memory);
}
@Override
public abstract List<String> getInputKeys();
@Override
public abstract List<String> getOutputKeys();
// TODO validation of input/outputs
@Override
public AiOutput apply(AiInput aiInput) {
AiInput aiInputToUse = preProcess(aiInput);
AiOutput aiOutput = doApply(aiInputToUse);
Map<String, Object> outputMapToUse = postProcess(aiInput, aiOutput);
return new AiOutput(outputMapToUse);
}
@Override
public AiInput preProcess(AiInput aiInput) {
validateInputs(aiInput.getInputData());
return aiInput;
}
protected abstract AiOutput doApply(AiInput aiInput);
@Override
public Map<String, Object> postProcess(AiInput aiInput, AiOutput aiOutput) {
validateOutputs(aiOutput.getOutputData());
Map<String, Object> combindedMap = new HashMap<>();
combindedMap.putAll(aiInput.getInputData());
combindedMap.putAll(aiOutput.getOutputData());
return combindedMap;
}
protected void validateOutputs(Map<String, Object> outputMap) {
Set<String> missingKeys = new HashSet<>(getOutputKeys());
missingKeys.removeAll(outputMap.keySet());
if (!missingKeys.isEmpty()) {
throw new IllegalArgumentException("Missing some output keys: " + missingKeys);
}
}
protected void validateInputs(Map<String, Object> inputMap) {
Set<String> missingKeys = new HashSet<>(getInputKeys());
missingKeys.removeAll(inputMap.keySet());
if (!missingKeys.isEmpty()) {
throw new IllegalArgumentException("Missing some input keys: " + missingKeys);
}
}
}

View File

@@ -1,17 +0,0 @@
package org.springframework.ai.chain;
import java.util.Map;
public class AiInput {
private Map<String, Object> inputData;
public AiInput(Map<String, Object> inputData) {
this.inputData = inputData;
}
Map<String, Object> getInputData() {
return inputData;
}
}

View File

@@ -1,17 +0,0 @@
package org.springframework.ai.chain;
import java.util.Map;
public class AiOutput {
private final Map<String, Object> outputData;
public AiOutput(Map<String, Object> outputData) {
this.outputData = outputData;
}
Map<String, Object> getOutputData() {
return this.outputData;
}
}

View File

@@ -1,17 +0,0 @@
package org.springframework.ai.chain;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
public interface Chain extends Function<AiInput, AiOutput> {
List<String> getInputKeys();
List<String> getOutputKeys();
AiInput preProcess(AiInput aiInput);
Map<String, Object> postProcess(AiInput aiInput, AiOutput aiOutput);
}

View File

@@ -1,22 +0,0 @@
package org.springframework.ai.memory;
import java.util.List;
import java.util.Map;
public interface Memory {
/**
* The keys that the memory will add to Chain inputs
*/
List<String> getKeys();
/**
* Return key-value pairs given the text input to the chain
* @param inputs input of the chain
* @return key-value pairs from memory
*/
Map<String, Object> load(Map<String, Object> inputs);
void save(Map<String, Object> inputs, Map<String, Object> outputs);
}

View File

@@ -1,88 +0,0 @@
package org.springframework.ai.chain;
import org.junit.jupiter.api.Test;
import org.springframework.ai.memory.Memory;
import java.util.List;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
class ChainTests {
@Test
void badInputs() {
Chain chain = new FakeChain();
AiInput aiInput = new AiInput(Map.of("foobar", "baz"));
assertThatThrownBy(() -> chain.apply(aiInput)).isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("Missing some input keys");
}
@Test
void correctInputs() {
Chain chain = new FakeChain();
AiInput aiInput = new AiInput(Map.of("foo", "bar"));
AiOutput aiOutput = chain.apply(aiInput);
assertThat(aiOutput.getOutputData()).containsEntry("foo", "bar").containsEntry("bar", "baz");
}
class FakeChain extends AbstractChain {
private boolean beCorrect = true;
private List<String> inputKeys = List.of("foo");
public FakeChain() {
}
public FakeChain(boolean beCorrect) {
this.beCorrect = beCorrect;
}
public FakeChain(List<String> inputKeys) {
this.inputKeys = inputKeys;
}
@Override
public List<String> getInputKeys() {
return this.inputKeys;
}
@Override
public List<String> getOutputKeys() {
return List.of("bar");
}
@Override
protected AiOutput doApply(AiInput aiInput) {
if (beCorrect) {
return new AiOutput(Map.of("bar", "baz"));
}
else {
return new AiOutput(Map.of("baz", "bar"));
}
}
}
class FakeMemory implements Memory {
@Override
public List<String> getKeys() {
return List.of("baz");
}
@Override
public Map<String, Object> load(Map<String, Object> inputs) {
return Map.of("baz", "foo");
}
@Override
public void save(Map<String, Object> inputs, Map<String, Object> outputs) {
}
}
}

View File

@@ -56,13 +56,6 @@ Output parsing employs meticulously crafted prompts, often necessitating multipl
This challenge has prompted OpenAI to introduce 'OpenAI Functions' as a means to specify the desired output format from the model precisely.
== Chaining Calls
A Chain is a concept that represents a series of calls to an AI model.
It uses the output from one call as the input to another.
By chaining calls together, you can support complex use cases by composing pipelines of multiple chains.
== Customizing Models: Integrating Your Data
How can you equip the AI model with information it hasn't been trained on?

View File

@@ -73,7 +73,6 @@ public class AcmeIT extends AbstractIT {
// Now user query
// This will be wrapped up in a chain
VectorStoreRetriever vectorStoreRetriever = new VectorStoreRetriever(vectorStore);
logger.info("Retrieving relevant documents");