Skip to content

Commit

Permalink
Switch to together AI
Browse files Browse the repository at this point in the history
  • Loading branch information
serefyarar committed May 27, 2024
1 parent cdb9846 commit 9dc35cf
Show file tree
Hide file tree
Showing 13 changed files with 289 additions and 251 deletions.
70 changes: 34 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@


<h1 align="center">
<a href="https://amplication.com/#gh-light-mode-only">
<img style="width:400px" src="https://index.network/images/IndexNetworkLogo.png">
Expand Down Expand Up @@ -32,83 +30,83 @@
</a>
</h4>


## About Index Network

Index is a discovery protocol that allows you to create truly personalized and autonomous discovery experiences across the web.

To achieve this, Index provides a decentralized semantic index that eliminates data fragmentation, a composable discovery protocol that allows data to be queried from multiple sources, in a user-centric manner. On top of this, it provides a real-time environment for agents that facilitates integration with algorithms and services and ensures that information acquires a fluid, social, and autonomous structure.



> [!NOTE]
> Full documentation and additional resources are available on the [Index Network documentation site →](https://docs.index.network)
> Full documentation and additional resources are available on the [Index Network documentation site →](https://docs.index.network)
## Table of contents
1. [Example](#examples)
3. [Components](#components)
4. [Getting started](#getting-started)
5. [Contributing](#contributing)
6. [Credits](#built-with-open-protocols)
7. [Resources](#resources)
8. [License](#license)

1. [Example](#examples)
2. [Components](#components)
3. [Getting started](#getting-started)
4. [Contributing](#contributing)
5. [Credits](#built-with-open-protocols)
6. [Resources](#resources)
7. [License](#license)

## Example

To illustrate, here is an example of an agent message that’s possible using Index Network:

<img style="width:100%" src="https://1670961284-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FLKYflEcLR5OkgHvFjnCP%2Fuploads%2FTAvgnyFgl4QfDP91yxXo%2Fusecase.png?alt=media&token=d1c012f8-7956-4eb6-8400-e57693fa3aed">




## Components

### Web App
The [Web App](web-app) component is where you can find the code for the web application. The web app provides a user-friendly interface that allows creators to explore indexes, manage their data, and configure them.

The [Web App](web-app) component is where you can find the code for the web application. The web app provides a user-friendly interface that allows creators to explore indexes, manage their data, and configure them.

### Indexer
The [Indexer](indexer) component hosts the code for the indexer. It acts as the backbone of the natural language operations, providing the necessary methods to consume data from Ceramic, interact with large language models. It listenes Apache Kafka to consume Ceramic Network events consumes to ChromaDB by running `yarn kafka-consumer`

The [Indexer](indexer) component hosts the code for the indexer. It acts as the backbone of the natural language operations, providing the necessary methods to consume data from Ceramic, interact with large language models. It listenes Apache Kafka to consume Ceramic Network events consumes to ChromaDB by running `yarn consumer`

### API

The [API](api) repository also hosts the code for all the API operations To start, you can simply run `yarn api`

Full protocol documentation can be found on the [Index Network documentation site →](https://docs.index.network)

### Ceramic Network Node
ComposeDB on Ceramic is a composable graph database built for Web3. Here you can find the steps to deploy along with an IPFS Node:

ComposeDB on Ceramic is a composable graph database built for Web3. Here you can find the steps to deploy along with an IPFS Node:
[https://composedb.js.org/docs/0.6.x/guides/composedb-server](https://composedb.js.org/docs/0.6.x/guides/composedb-server)

### IPFS Node
ComposeDB on Ceramic is a composable graph database built for Web3. Here you can find the steps to deploy along with an IPFS Node:

ComposeDB on Ceramic is a composable graph database built for Web3. Here you can find the steps to deploy along with an IPFS Node:
[https://composedb.js.org/docs/0.6.x/guides/composedb-server](https://composedb.js.org/docs/0.6.x/guides/composedb-server)

### Others
We use [PostgreSQL](https://www.postgresql.org/) indexing feature of [Ceramic Network](https://ceramic.network/) and use [KafkaConnect CDC](https://docs.confluent.io/cloud/current/connectors/cc-postgresql-source.html) to produce db changes to [Apache Kafka](https://kafka.apache.org/) and finally write data to [ChromaDB](https://www.trychroma.com/) via the consumer service.

We use [PostgreSQL](https://www.postgresql.org/) indexing feature of [Ceramic Network](https://ceramic.network/) and use [KafkaConnect CDC](https://docs.confluent.io/cloud/current/connectors/cc-postgresql-source.html) to produce db changes to [Apache Kafka](https://kafka.apache.org/) and finally write data to [ChromaDB](https://www.trychroma.com/) via the consumer service.

## Getting started

This code snippet demonstrates how to interact with the protocol using the Index client. It begins by initializing the client for and authenticating with a DID session. Then, it creates an index titled "Future of publishing" and a web page titled "Post medium publishing" with a specified URL. The code adds the web page to the index and performs a natural language query using the keyword "summarize," retrieving and displaying the natural language query response.

```js
const indexClient = new Index({
network: "testnet"
network: "testnet",
});

indexClient.authenticate(session)
indexClient.authenticate(session);

// Create an index
const indexId = await indexClient.createIndex({
title: "Future of publishing",
signerPublicKey: "0x047955f0df748d..1708fc8c965",
signerFunction: "QmaD9FZJYst2Tntf9UwSd3QUeD68XpaPhKBSyy5wWLHq2m"
signerFunction: "QmaD9FZJYst2Tntf9UwSd3QUeD68XpaPhKBSyy5wWLHq2m",
});

// Create a web page
const webPageId = await indexClient.createWebPage({
title: "Post medium publishing",
url: "http://www.paulgraham.com/publishing.html"
url: "http://www.paulgraham.com/publishing.html",
});

// Add the web page to the index
Expand All @@ -117,21 +115,19 @@ await indexClient.addIndexItem(indexId, webPageId);
// Perform a natural language query
const queryResponse = await indexClient.query({
query: "summarize",
indexes: [indexId]
indexes: [indexId],
});

console.log("Query response:", queryResponse);

```


```json
{
"response": "This article discusses the intricacies and challenges of publishing in the modern digital era, emphasizing the importance of content quality and audience engagement. The author shares insights from personal experiences and outlines strategies for successful online publishing.",
"sources": [
"sources": [
{
"itemId": "kjzl6kcym7w8y7fjc89gmnkne7qpdz5ws5ryfji3i8dndjh2wxuii7z1anybovo",
"indexId": "indexIdValue",
"indexId": "indexIdValue"
}
]
}
Expand All @@ -140,6 +136,7 @@ console.log("Query response:", queryResponse);
## Contributing

First of all, thanks for thinking of contributing to this project. Before sending a Pull Request, please make sure that you're assigned the task on a GitHub issue.

- If a relevant issue already exists, discuss on the issue and get it assigned to yourself on GitHub.
- If no relevant issue exists, open a new issue and get it assigned to yourself on GitHub.

Expand All @@ -155,10 +152,11 @@ Index Network leverages the power of several open protocols to enhance its capab

## Resources

- **[Index Network](https://index.network)** to explore the app.
- **[Discord](https://discord.gg/wvdxP6XvYu)** for support and discussions with the community and the team.
- **[GitHub](https://github.com/indexas/indexas)** for source code, project board, issues, and pull requests.
- **[Twitter](https://twitter.com/indexas)** for the latest updates on the product and published blogs.
- **[Index Network](https://index.network)** to explore the app.
- **[Discord](https://discord.gg/wvdxP6XvYu)** for support and discussions with the community and the team.
- **[GitHub](https://github.com/indexas/indexas)** for source code, project board, issues, and pull requests.
- **[Twitter](https://twitter.com/indexas)** for the latest updates on the product and published blogs.

## License
Index Network is under the MIT license. See the [LICENSE](LICENSE) for more information.

Index Network is under the MIT license. See the [LICENSE](LICENSE) for more information.
4 changes: 2 additions & 2 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"scripts": {
"api": "node --experimental-specifier-resolution=node --experimental-fetch src/packages/api.js",
"dev-api": "nodemon --experimental-fetch src/packages/api.js",
"dev-kafka": "nodemon --experimental-fetch src/packages/consumer.js",
"kafka-consumer": "node --experimental-fetch src/packages/consumer.js",
"dev-consumer": "nodemon --experimental-fetch src/packages/consumer.js",
"consumer": "node --experimental-fetch src/packages/consumer.js",
"swagger": "npx swagger-typescript-api -p protocol.yaml -o ./src -n protocol.ts",
"reIndex": "node --experimental-fetch src/utils/reIndex.js"
},
Expand Down
Empty file added api/priv.key
Empty file.
11 changes: 8 additions & 3 deletions api/src/packages/consumer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { createClient } from "redis";
const ceramicFirehose = new EventSource(
`${process.env.CERAMIC_HOST}/api/v0/feed/aggregation/documents`,
);
const Codec = JsonAsString.pipe(AggregationDocument);

const redis = RedisClient.getInstance();

Expand All @@ -25,16 +26,20 @@ const subClient = createClient({

async function start() {
await subClient.connect();
await redis.connect();
let { runtimeDefinition, modelFragments } = await fetchModelInfo();
let indexer = new Indexer(runtimeDefinition, modelFragments);
subClient.subscribe("newModel", async (id) => {
console.log("New model detected, fetching model info", id);
({ runtimeDefinition, modelFragments } = await fetchModelInfo());
indexer = new Indexer(runtimeDefinition, modelFragments);
});
await redis.connect();

const Codec = JsonAsString.pipe(AggregationDocument);
subClient.subscribe("reIndex", async (id) => {
console.log("Reindex an item through external redis subscription.", id);
await indexer.createIndexItemEvent(id);
});

const indexer = new Indexer(runtimeDefinition, modelFragments);
ceramicFirehose.addEventListener("message", async (event) => {
const parsedData = decode(Codec, event.data);
const modelId = parsedData.metadata.model.toString();
Expand Down
9 changes: 7 additions & 2 deletions indexer/src/app/modules/agent.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ChatOpenAI, OpenAI, OpenAIEmbeddings } from '@langchain/openai';
import { ChatOpenAI, OpenAI } from '@langchain/openai';
import { TogetherAIEmbeddings } from '@langchain/community/embeddings/togetherai';

import { loadSummarizationChain } from 'langchain/chains';
import {
RunnableLambda,
Expand Down Expand Up @@ -164,7 +166,10 @@ export class Agent {
}

const vectorStore = await Chroma.fromExistingCollection(
new OpenAIEmbeddings({ modelName: process.env.MODEL_EMBEDDING }),
new TogetherAIEmbeddings({
apiKey: process.env.TOGETHER_AI_API_KEY,
modelName: process.env.MODEL_EMBEDDING,
}),
{
url: process.env.CHROMA_URL,
collectionName: process.env.CHROMA_COLLECTION_NAME,
Expand Down
89 changes: 47 additions & 42 deletions indexer/src/app/modules/chroma.module.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,57 @@
import { DynamicModule, Global, Logger, Module } from '@nestjs/common';
import { Chroma } from '@langchain/community/vectorstores/chroma';
import { OpenAIEmbeddings } from '@langchain/openai';
import { TogetherAIEmbeddings } from '@langchain/community/embeddings/togetherai';

@Global()
@Module({})
export class ChromaModule {
static register (apiKey: string): DynamicModule {
return {
module: ChromaModule,
global: true,
providers: [
{
provide: 'CHROMA_DB',
useFactory: async (): Promise<Chroma> => {
try {
static register(apiKey: string): DynamicModule {
return {
module: ChromaModule,
global: true,
providers: [
{
provide: 'CHROMA_DB',
useFactory: async (): Promise<Chroma> => {
try {
if (!process.env.OPENAI_API_KEY)
throw new Error('OpenAI API key is required');

if (!process.env.OPENAI_API_KEY) throw new Error('OpenAI API key is required');

Logger.debug(process.env.CHROMA_URL, 'ChromaModule');
Logger.debug(process.env.CHROMA_COLLECTION_NAME, 'ChromaModule');
Logger.debug(process.env.CHROMA_URL, 'ChromaModule');
Logger.debug(process.env.CHROMA_COLLECTION_NAME, 'ChromaModule');

const vectorStore = await Chroma.fromExistingCollection(
new OpenAIEmbeddings({
openAIApiKey: apiKey,
modelName: process.env.MODEL_EMBEDDING,
}),
{
collectionName: process.env.CHROMA_COLLECTION_NAME,
url: process.env.CHROMA_URL,
}
);

const ensure = await vectorStore.ensureCollection();
Logger.debug(JSON.stringify(ensure), 'ChromaModule:ensureCollection');
const vectorStore = await Chroma.fromExistingCollection(
new TogetherAIEmbeddings({
apiKey: process.env.TOGETHER_AI_API_KEY,
modelName: process.env.MODEL_EMBEDDING,
}),
{
collectionName: process.env.CHROMA_COLLECTION_NAME,
url: process.env.CHROMA_URL,
},
);

const docCount = await vectorStore.collection.count();
Logger.debug(`Loaded ${docCount} documents from ChromaDB`, 'ChromaModule');
const ensure = await vectorStore.ensureCollection();
Logger.debug(
JSON.stringify(ensure),
'ChromaModule:ensureCollection',
);

return vectorStore;

} catch (e) {
Logger.error('ChromaDB connection failure:', e, 'ChromaDBModule');
throw new Error('CHROMADB_CONNECTION_FAILURE');
}
},
},
],
exports: ['CHROMA_DB'],
};
}
}
const docCount = await vectorStore.collection.count();
Logger.debug(
`Loaded ${docCount} documents from ChromaDB`,
'ChromaModule',
);

return vectorStore;
} catch (e) {
Logger.error('ChromaDB connection failure:', e, 'ChromaDBModule');
throw new Error('CHROMADB_CONNECTION_FAILURE');
}
},
},
],
exports: ['CHROMA_DB'],
};
}
}
1 change: 0 additions & 1 deletion indexer/src/chat/service/chat.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {

import { Agent } from 'src/app/modules/agent.module';
import { RunnableSequence } from '@langchain/core/runnables';
import { OpenAIEmbeddings } from '@langchain/openai';

@Injectable()
export class ChatService {
Expand Down
6 changes: 3 additions & 3 deletions indexer/src/indexer/service/indexer.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { HttpStatus, Inject, Injectable, Logger } from '@nestjs/common';
import { Chroma } from '@langchain/community/vectorstores/chroma';
import { OpenAIEmbeddings } from '@langchain/openai';
import { UnstructuredLoader } from 'langchain/document_loaders/fs/unstructured';
import { JSONLoader } from 'langchain/document_loaders/fs/json';

Expand All @@ -9,6 +8,7 @@ import { HttpService } from '@nestjs/axios';
import * as fs from 'fs';
import { MIME_TYPE } from '../schema/indexer.schema';
import { TokenTextSplitter } from 'langchain/text_splitter';
import { TogetherAIEmbeddings } from '@langchain/community/embeddings/togetherai';

@Injectable()
export class IndexerService {
Expand Down Expand Up @@ -324,9 +324,9 @@ export class IndexerService {
if (!content) return HttpStatus.OK;

try {
const embeddings = new OpenAIEmbeddings({
const embeddings = new TogetherAIEmbeddings({
apiKey: process.env.TOGETHER_AI_API_KEY,
modelName: process.env.MODEL_EMBEDDING,
openAIApiKey: process.env.OPENAI_API_KEY,
});

Logger.log(
Expand Down
Loading

0 comments on commit 9dc35cf

Please sign in to comment.