Compare commits

..

24 Commits

Author SHA1 Message Date
sweep-ai[bot] babc6a0242 Merge main into sweep/add-evaluation-method 2023-11-14 17:16:34 +00:00
sweep-ai[bot] e97d4af275 Merge main into sweep/add-evaluation-method 2023-11-14 17:09:22 +00:00
sweep-ai[bot] 5ee9af361d Merge main into sweep/add-evaluation-method 2023-11-14 04:20:00 +00:00
sweep-ai[bot] 9a07e71243 Merge main into sweep/add-evaluation-method 2023-11-14 04:00:12 +00:00
sweep-ai[bot] a7ee7c9e35 Merge main into sweep/add-evaluation-method 2023-11-14 02:10:44 +00:00
sweep-ai[bot] 9ae305baa8 Merge main into sweep/add-evaluation-method 2023-11-14 02:02:16 +00:00
sweep-ai[bot] 83745aa579 Merge main into sweep/add-evaluation-method 2023-11-14 01:59:06 +00:00
sweep-ai[bot] 029eda4166 Merge main into sweep/add-evaluation-method 2023-11-10 03:12:29 +00:00
sweep-ai[bot] 8ddfcbfb93 Merge main into sweep/add-evaluation-method 2023-11-06 20:59:04 +00:00
sweep-ai[bot] 13b555ffc7 Merge main into sweep/add-evaluation-method 2023-11-06 20:58:31 +00:00
sweep-ai[bot] b50d254e50 Merge main into sweep/add-evaluation-method 2023-11-06 19:00:15 +00:00
sweep-ai[bot] 2c045643a8 Merge main into sweep/add-evaluation-method 2023-11-06 18:51:14 +00:00
sweep-ai[bot] d7dafc3ec4 Merge main into sweep/add-evaluation-method 2023-11-03 01:05:39 +00:00
sweep-ai[bot] e8d8e3df59 Merge main into sweep/add-evaluation-method 2023-10-30 20:59:23 +00:00
sweep-ai[bot] dbd4e1c892 Merge main into sweep/add-evaluation-method 2023-10-30 17:56:41 +00:00
sweep-ai[bot] 86e4242f04 feat: Updated packages/core/src/QueryResponseEvalu 2023-10-30 11:36:11 +00:00
sweep-ai[bot] 4f02b0ad98 feat: Updated packages/core/src/QueryResponseEvalu 2023-10-30 11:35:01 +00:00
sweep-ai[bot] 21024425cb feat: Updated CI/CD configuration file 2023-10-30 11:32:40 +00:00
sweep-ai[bot] cdc129aeaa feat: Updated CI/CD configuration file 2023-10-30 11:31:34 +00:00
sweep-ai[bot] c1c1910f11 feat: Updated CONTRIBUTING.md 2023-10-30 11:30:14 +00:00
sweep-ai[bot] 06a7a6bfdd feat: Add QueryResponseEvaluator class for evaluat 2023-10-30 11:29:08 +00:00
sweep-ai[bot] 6b831632fa feat: Update CI/CD pipeline to run eslint on .js a 2023-10-30 11:27:30 +00:00
sweep-ai[bot] 96a7ed14aa feat: Updated CONTRIBUTING.md 2023-10-30 11:26:25 +00:00
sweep-ai[bot] 60d0864043 feat: Add ResponseEvaluator class for response eva 2023-10-30 11:25:11 +00:00
49 changed files with 771 additions and 1358 deletions
-5
View File
@@ -1,5 +0,0 @@
---
"create-llama": patch
---
Label bug fix
-1
View File
@@ -2,4 +2,3 @@
. "$(dirname -- "$0")/_/husky.sh"
pnpm lint
npx lint-staged
+27
View File
@@ -0,0 +1,27 @@
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Cache Node.js modules
uses: actions/cache@v2
with:
path: ~/.pnpm-store
key: ${{ runner.OS }}-node-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.OS }}-node-
- run: pnpm install
- run: pnpm eslint --fix "./**/*.ts" "./**/*.js"
- run: pnpm run test
+12 -2
View File
@@ -31,11 +31,21 @@ PNPM's has documentation on its [workspace feature](https://pnpm.io/workspaces)
### Running Typescript
When we publish to NPM we will have a tsc compiled version of the library in JS. For now, the easiest thing to do is use ts-node.
When we publish to NPM we will have a tsc compiled version of the library in JS. For now, the easiest thing to do is use ts-node. To run a TypeScript file, use the following command:
```
pnpx ts-node {file_path}
```
### Test cases
To run them, run
Before running the tests, compile the TypeScript files to JavaScript. This can be done by running the following command:
```
pnpm run build
```
After the build process is complete, you can run the tests with:
```
pnpm run test
+1 -1
View File
@@ -89,7 +89,7 @@ Check out our NextJS playground at https://llama-playground.vercel.app/. The sou
If you're using NextJS App Router, you'll need to use the NodeJS runtime (default) and add the follow config to your next.config.js to have it use imports/exports in the same way Node does.
```js
export const runtime = "nodejs"; // default
export const runtime = "nodejs" // default
```
```js
-2
View File
@@ -6,8 +6,6 @@ sidebar_position: 4
We include several end-to-end examples using LlamaIndex.TS in the repository
Check out the examples below or try them out and complete them in minutes with interactive Github Codespace tutorials provided by Dev-Docs [here](https://codespaces.new/team-dev-docs/lits-dev-docs-playground?devcontainer_path=.devcontainer%2Fjavascript_ltsquickstart%2Fdevcontainer.json):
## [Chat Engine](https://github.com/run-llama/LlamaIndexTS/blob/main/apps/simple/chatEngine.ts)
Read a file and chat about it with the LLM.
+1 -1
View File
@@ -11,7 +11,7 @@ LlamaIndex currently officially supports NodeJS 18 and NodeJS 20.
If you're using NextJS App Router route handlers/serverless functions, you'll need to use the NodeJS mode:
```js
export const runtime = "nodejs"; // default
export const runtime = "nodejs" // default
```
and you'll need to add an exception for pdf-parse in your next.config.js
+1 -1
View File
@@ -6,7 +6,7 @@ import readline from "node:readline/promises";
import { ChatMessage, LlamaDeuce, OpenAI } from "llamaindex";
(async () => {
const gpt4 = new OpenAI({ model: "gpt-4", temperature: 0.9 });
const gpt4 = new OpenAI({ model: "gpt-4-vision-preview", temperature: 0.9 });
const l2 = new LlamaDeuce({
model: "Llama-2-70b-chat-4bit",
temperature: 0.9,
+2 -2
View File
@@ -1,7 +1,7 @@
import { ChatMessage, SimpleChatEngine } from "llamaindex";
import { ChatMessage, OpenAI, SimpleChatEngine } from "llamaindex";
import {Anthropic} from "../../packages/core/src/llm/LLM";
import { stdin as input, stdout as output } from "node:process";
import readline from "node:readline/promises";
import { Anthropic } from "../../packages/core/src/llm/LLM";
async function main() {
const query: string = `
+1 -1
View File
@@ -1,6 +1,6 @@
import { MongoClient } from "mongodb";
import { Document } from "../../packages/core/src/Node";
import { VectorStoreIndex } from "../../packages/core/src/indices";
import { Document } from "../../packages/core/src/Node";
import { SimpleMongoReader } from "../../packages/core/src/readers/SimpleMongoReader";
import { stdin as input, stdout as output } from "node:process";
+11 -11
View File
@@ -1,23 +1,23 @@
import { Portkey } from "llamaindex";
(async () => {
const llms = [{}];
const llms = [{
}]
const portkey = new Portkey({
mode: "single",
llms: [
{
provider: "anyscale",
virtual_key: "anyscale-3b3c04",
model: "meta-llama/Llama-2-13b-chat-hf",
max_tokens: 2000,
},
],
llms: [{
provider:"anyscale",
virtual_key:"anyscale-3b3c04",
model: "meta-llama/Llama-2-13b-chat-hf",
max_tokens: 2000
}]
});
const result = portkey.stream_chat([
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Tell me a joke." },
{ role: "user", content: "Tell me a joke." }
]);
for await (const res of result) {
process.stdout.write(res);
process.stdout.write(res)
}
})();
-24
View File
@@ -1,24 +0,0 @@
import { SimpleDirectoryReader } from "llamaindex";
function callback(
category: string,
name: string,
status: any,
message?: string,
): boolean {
console.log(category, name, status, message);
if (name.endsWith(".pdf")) {
console.log("I DON'T WANT PDF FILES!");
return false;
}
return true;
}
async function main() {
// Load page
const reader = new SimpleDirectoryReader(callback);
const params = { directoryPath: "./data" };
await reader.loadData(params);
}
main().catch(console.error);
-21
View File
@@ -1,21 +0,0 @@
import { HTMLReader, VectorStoreIndex } from "llamaindex";
async function main() {
// Load page
const reader = new HTMLReader();
const documents = await reader.loadData("data/18-1_Changelog.html");
// Split text and create embeddings. Store them in a VectorStoreIndex
const index = await VectorStoreIndex.fromDocuments(documents);
// Query the index
const queryEngine = index.asQueryEngine();
const response = await queryEngine.query(
"What were the notable changes in 18.1?",
);
// Output response
console.log(response.toString());
}
main().catch(console.error);
-47
View File
@@ -1,47 +0,0 @@
import { ChatMessage, SimpleChatEngine } from "llamaindex";
import { stdin as input, stdout as output } from "node:process";
import readline from "node:readline/promises";
import { Anthropic } from "../../packages/core/src/llm/LLM";
async function main() {
const query: string = `
Where is Istanbul?
`;
// const llm = new OpenAI({ model: "gpt-3.5-turbo", temperature: 0.1 });
const llm = new Anthropic();
const message: ChatMessage = { content: query, role: "user" };
//TODO: Add callbacks later
//Stream Complete
//Note: Setting streaming flag to true or false will auto-set your return type to
//either an AsyncGenerator or a Response.
// Omitting the streaming flag automatically sets streaming to false
const chatEngine: SimpleChatEngine = new SimpleChatEngine({
chatHistory: undefined,
llm: llm,
});
const rl = readline.createInterface({ input, output });
while (true) {
const query = await rl.question("Query: ");
if (!query) {
break;
}
//Case 1: .chat(query, undefined, true) => Stream
//Case 2: .chat(query, undefined, false) => Response object
//Case 3: .chat(query, undefined) => Response object
const chatStream = await chatEngine.chat(query, undefined, true);
var accumulated_result = "";
for await (const part of chatStream) {
accumulated_result += part;
process.stdout.write(part);
}
}
}
main();
-68
View File
@@ -1,68 +0,0 @@
import { MongoClient } from "mongodb";
import { Document } from "../../packages/core/src/Node";
import { VectorStoreIndex } from "../../packages/core/src/indices";
import { SimpleMongoReader } from "../../packages/core/src/readers/SimpleMongoReader";
import { stdin as input, stdout as output } from "node:process";
import readline from "node:readline/promises";
async function main() {
//Dummy test code
const query: object = { _id: "waldo" };
const options: object = {};
const projections: object = { embedding: 0 };
const limit: number = Infinity;
const uri: string = process.env.MONGODB_URI ?? "fake_uri";
const client: MongoClient = new MongoClient(uri);
//Where the real code starts
const MR = new SimpleMongoReader(client);
const documents: Document[] = await MR.loadData(
"data",
"posts",
1,
{},
options,
projections,
);
//
//If you need to look at low-level details of
// a queryEngine (for example, needing to check each individual node)
//
// Split text and create embeddings. Store them in a VectorStoreIndex
// var storageContext = await storageContextFromDefaults({});
// var serviceContext = serviceContextFromDefaults({});
// const docStore = storageContext.docStore;
// for (const doc of documents) {
// docStore.setDocumentHash(doc.id_, doc.hash);
// }
// const nodes = serviceContext.nodeParser.getNodesFromDocuments(documents);
// console.log(nodes);
//
//Making Vector Store from documents
//
const index = await VectorStoreIndex.fromDocuments(documents);
// Create query engine
const queryEngine = index.asQueryEngine();
const rl = readline.createInterface({ input, output });
while (true) {
const query = await rl.question("Query: ");
if (!query) {
break;
}
const response = await queryEngine.query(query);
// Output response
console.log(response.toString());
}
}
main();
+11 -11
View File
@@ -1,23 +1,23 @@
import { Portkey } from "llamaindex";
(async () => {
const llms = [{}];
const llms = [{
}]
const portkey = new Portkey({
mode: "single",
llms: [
{
provider: "anyscale",
virtual_key: "anyscale-3b3c04",
model: "meta-llama/Llama-2-13b-chat-hf",
max_tokens: 2000,
},
],
llms: [{
provider:"anyscale",
virtual_key:"anyscale-3b3c04",
model: "meta-llama/Llama-2-13b-chat-hf",
max_tokens: 2000
}]
});
const result = portkey.stream_chat([
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Tell me a joke." },
{ role: "user", content: "Tell me a joke." }
]);
for await (const res of result) {
process.stdout.write(res);
process.stdout.write(res)
}
})();
+1 -10
View File
@@ -3,7 +3,6 @@ import {
OpenAI,
RetrieverQueryEngine,
serviceContextFromDefaults,
SimilarityPostprocessor,
VectorStoreIndex,
} from "llamaindex";
import essay from "./essay";
@@ -22,16 +21,8 @@ async function main() {
const retriever = index.asRetriever();
retriever.similarityTopK = 5;
const nodePostprocessor = new SimilarityPostprocessor({
similarityCutoff: 0.7,
});
// TODO: cannot pass responseSynthesizer into retriever query engine
const queryEngine = new RetrieverQueryEngine(
retriever,
undefined,
undefined,
[nodePostprocessor],
);
const queryEngine = new RetrieverQueryEngine(retriever);
const response = await queryEngine.query(
"What did the author do growing up?",
-197
View File
@@ -1,197 +0,0 @@
import {
OpenAI,
ResponseSynthesizer,
RetrieverQueryEngine,
serviceContextFromDefaults,
TextNode,
TreeSummarize,
VectorIndexRetriever,
VectorStore,
VectorStoreIndex,
VectorStoreQuery,
VectorStoreQueryResult,
} from "llamaindex";
import { Index, Pinecone, RecordMetadata } from "@pinecone-database/pinecone";
/**
* Please do not use this class in production; it's only for demonstration purposes.
*/
class PineconeVectorStore<T extends RecordMetadata = RecordMetadata>
implements VectorStore
{
storesText = true;
isEmbeddingQuery = false;
indexName!: string;
pineconeClient!: Pinecone;
index!: Index<T>;
constructor({ indexName, client }: { indexName: string; client: Pinecone }) {
this.indexName = indexName;
this.pineconeClient = client;
this.index = client.index<T>(indexName);
}
client() {
return this.pineconeClient;
}
async query(
query: VectorStoreQuery,
kwargs?: any,
): Promise<VectorStoreQueryResult> {
let queryEmbedding: number[] = [];
if (query.queryEmbedding) {
if (typeof query.alpha === "number") {
const alpha = query.alpha;
queryEmbedding = query.queryEmbedding.map((v) => v * alpha);
} else {
queryEmbedding = query.queryEmbedding;
}
}
// Current LlamaIndexTS implementation only support exact match filter, so we use kwargs instead.
const filter = kwargs?.filter || {};
const response = await this.index.query({
filter,
vector: queryEmbedding,
topK: query.similarityTopK,
includeValues: true,
includeMetadata: true,
});
console.log(
`Numbers of vectors returned by Pinecone after preFilters are applied: ${
response?.matches?.length || 0
}.`,
);
const topKIds: string[] = [];
const topKNodes: TextNode[] = [];
const topKScores: number[] = [];
const metadataToNode = (metadata?: T): Partial<TextNode> => {
if (!metadata) {
throw new Error("metadata is undefined.");
}
const nodeContent = metadata["_node_content"];
if (!nodeContent) {
throw new Error("nodeContent is undefined.");
}
if (typeof nodeContent !== "string") {
throw new Error("nodeContent is not a string.");
}
return JSON.parse(nodeContent);
};
if (response.matches) {
for (const match of response.matches) {
const node = new TextNode({
...metadataToNode(match.metadata),
embedding: match.values,
});
topKIds.push(match.id);
topKNodes.push(node);
topKScores.push(match.score ?? 0);
}
}
const result = {
ids: topKIds,
nodes: topKNodes,
similarities: topKScores,
};
return result;
}
add(): Promise<string[]> {
return Promise.resolve([]);
}
delete(): Promise<void> {
throw new Error("Method `delete` not implemented.");
}
persist(): Promise<void> {
throw new Error("Method `persist` not implemented.");
}
}
/**
* The goal of this example is to show how to use Pinecone as a vector store
* for LlamaIndexTS with(out) preFilters.
*
* It should not be used in production like that,
* as you might want to find a proper PineconeVectorStore implementation.
*/
async function main() {
process.env.PINECONE_API_KEY = "Your Pinecone API Key.";
process.env.PINECONE_ENVIRONMENT = "Your Pinecone Environment.";
process.env.PINECONE_PROJECT_ID = "Your Pinecone Project ID.";
process.env.PINECONE_INDEX_NAME = "Your Pinecone Index Name.";
process.env.OPENAI_API_KEY = "Your OpenAI API Key.";
process.env.OPENAI_API_ORGANIZATION = "Your OpenAI API Organization.";
const getPineconeVectorStore = async () => {
return new PineconeVectorStore({
indexName: process.env.PINECONE_INDEX_NAME || "index-name",
client: new Pinecone(),
});
};
const getServiceContext = () => {
const openAI = new OpenAI({
model: "gpt-4",
apiKey: process.env.OPENAI_API_KEY,
});
return serviceContextFromDefaults({
llm: openAI,
});
};
const getQueryEngine = async (filter: unknown) => {
const vectorStore = await getPineconeVectorStore();
const serviceContext = getServiceContext();
const vectorStoreIndex = await VectorStoreIndex.fromVectorStore(
vectorStore,
serviceContext,
);
const retriever = new VectorIndexRetriever({
index: vectorStoreIndex,
similarityTopK: 500,
});
const responseSynthesizer = new ResponseSynthesizer({
serviceContext,
responseBuilder: new TreeSummarize(serviceContext),
});
return new RetrieverQueryEngine(retriever, responseSynthesizer, {
filter,
});
};
// whatever is a key from your metadata
const queryEngine = await getQueryEngine({
whatever: {
$gte: 1,
$lte: 100,
},
});
const response = await queryEngine.query("How many results do you have?");
console.log(response.toString());
}
main().catch(console.error);
-15
View File
@@ -1,15 +0,0 @@
import { OpenAI } from "llamaindex";
(async () => {
const llm = new OpenAI({ model: "gpt-4-vision-preview", temperature: 0.1 });
// complete api
const response1 = await llm.complete("How are you?");
console.log(response1.message.content);
// chat api
const response2 = await llm.chat([
{ content: "Tell me a joke!", role: "user" },
]);
console.log(response2.message.content);
})();
+9 -11
View File
@@ -3,7 +3,7 @@
"scripts": {
"build": "turbo run build",
"dev": "turbo run dev",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,md}\"",
"format": "prettier --write \"**/*.{ts,tsx,md}\"",
"lint": "turbo run lint",
"prepare": "husky install",
"test": "turbo run test",
@@ -11,27 +11,25 @@
"publish-snapshot": "turbo run build lint test && changeset version --snapshot && changeset publish"
},
"devDependencies": {
"@changesets/cli": "^2.26.2",
"@turbo/gen": "^1.10.16",
"@types/jest": "^29.5.8",
"eslint": "^8.53.0",
"@types/jest": "^29.5.6",
"eslint": "^8.52.0",
"eslint-config-custom": "workspace:*",
"husky": "^8.0.3",
"jest": "^29.7.0",
"lint-staged": "^15.1.0",
"prettier": "^3.1.0",
"prettier-plugin-organize-imports": "^3.2.4",
"prettier": "^3.0.3",
"prettier-plugin-organize-imports": "^3.2.3",
"ts-jest": "^29.1.1",
"turbo": "^1.10.16"
},
"packageManager": "pnpm@8.10.5+sha256.a4bd9bb7b48214bbfcd95f264bd75bb70d100e5d4b58808f5cd6ab40c6ac21c5",
"packageManager": "pnpm@8.10.4+sha256.df3202c6c8fd345be5ba6a4199297582d5bebf8963822aa3344f4cd2b8be8d43",
"dependencies": {
"@changesets/cli": "^2.26.2"
},
"pnpm": {
"overrides": {
"trim": "1.0.1",
"@babel/traverse": "7.23.2"
}
},
"lint-staged": {
"*.{js,jsx,ts,tsx,md}": "prettier --write"
}
}
+1 -1
View File
@@ -16,7 +16,7 @@
"pdf-parse": "^1.1.1",
"portkey-ai": "^0.1.16",
"rake-modified": "^1.0.8",
"replicate": "^0.21.1",
"replicate": "^0.20.1",
"string-strip-html": "^13.4.3",
"uuid": "^9.0.1",
"wink-nlp": "^1.14.3"
+5 -5
View File
@@ -1,4 +1,4 @@
import { encodingForModel } from "js-tiktoken";
import { encodingForModel, TiktokenModel } from "js-tiktoken";
import { v4 as uuidv4 } from "uuid";
import { Event, EventTag, EventType } from "./callbacks/CallbackManager";
@@ -27,7 +27,7 @@ class GlobalsHelper {
const numberArray = Array.from(tokens);
const text = encoding.decode(numberArray);
const uint8Array = new TextEncoder().encode(text);
return new TextDecoder().decode(uint8Array);
return new TextDecoder().decode(uint8Array);
},
};
}
@@ -39,10 +39,10 @@ class GlobalsHelper {
if (!this.defaultTokenizer) {
this.initDefaultTokenizer();
}
return this.defaultTokenizer!.encode.bind(this.defaultTokenizer);
}
tokenizerDecoder(encoding?: string) {
if (encoding && encoding !== Tokenizers.CL100K_BASE) {
throw new Error(`Tokenizer encoding ${encoding} not yet supported`);
@@ -50,7 +50,7 @@ class GlobalsHelper {
if (!this.defaultTokenizer) {
this.initDefaultTokenizer();
}
return this.defaultTokenizer!.decode.bind(this.defaultTokenizer);
}
+2 -2
View File
@@ -1,4 +1,6 @@
import { v4 as uuidv4 } from "uuid";
import { Event } from "./callbacks/CallbackManager";
import { BaseNodePostprocessor } from "./indices/BaseNodePostprocessor";
import { NodeWithScore, TextNode } from "./Node";
import {
BaseQuestionGenerator,
@@ -10,8 +12,6 @@ import { CompactAndRefine, ResponseSynthesizer } from "./ResponseSynthesizer";
import { BaseRetriever } from "./Retriever";
import { ServiceContext, serviceContextFromDefaults } from "./ServiceContext";
import { QueryEngineTool, ToolMetadata } from "./Tool";
import { Event } from "./callbacks/CallbackManager";
import { BaseNodePostprocessor } from "./indices/BaseNodePostprocessor";
/**
* A query engine is a question answerer that can use one or more steps.
@@ -0,0 +1,12 @@
import { Response } from './Response';
import { BaseQueryEngine } from './QueryEngine';
import { ResponseEvaluator } from './ResponseEvaluator';
export class QueryResponseEvaluator {
evaluate(query: string, response: Response, queryEngine: BaseQueryEngine): number {
const evaluator = new ResponseEvaluator(queryEngine);
const binaryEvaluation = evaluator.binaryEvaluation(query, response);
const nodeEvaluation = evaluator.nodeEvaluation(query, response);
return binaryEvaluation && nodeEvaluation ? 1 : 0;
}
}
+12
View File
@@ -0,0 +1,12 @@
import { Response } from './Response';
import { BaseNode } from './Node';
export class ResponseEvaluator {
binaryEvaluation(response: Response, context: string): boolean {
return response.toString() === context;
}
nodeEvaluation(query: string, node: BaseNode): boolean {
return node.toString().includes(query);
}
}
+12 -12
View File
@@ -1,7 +1,11 @@
export * from "./callbacks/CallbackManager";
export * from "./ChatEngine";
export * from "./ChatHistory";
export * from "./constants";
export * from "./Embedding";
export * from "./GlobalsHelper";
export * from "./indices";
export * from "./llm/LLM";
export * from "./Node";
export * from "./NodeParser";
export * from "./OutputParser";
@@ -9,21 +13,17 @@ export * from "./Prompt";
export * from "./PromptHelper";
export * from "./QueryEngine";
export * from "./QuestionGenerator";
export * from "./readers/base";
export * from "./readers/CSVReader";
export * from "./readers/MarkdownReader";
export * from "./readers/NotionReader";
export * from "./readers/PDFReader";
export * from "./readers/HTMLReader";
export * from "./readers/SimpleDirectoryReader";
export * from "./Response";
export * from "./ResponseSynthesizer";
export * from "./Retriever";
export * from "./ServiceContext";
export * from "./storage";
export * from "./TextSplitter";
export * from "./Tool";
export * from "./callbacks/CallbackManager";
export * from "./constants";
export * from "./indices";
export * from "./llm/LLM";
export * from "./readers/CSVReader";
export * from "./readers/HTMLReader";
export * from "./readers/MarkdownReader";
export * from "./readers/NotionReader";
export * from "./readers/PDFReader";
export * from "./readers/SimpleDirectoryReader";
export * from "./readers/base";
export * from "./storage";
@@ -10,11 +10,11 @@ import {
ServiceContext,
serviceContextFromDefaults,
} from "../../ServiceContext";
import { BaseDocumentStore, RefDocInfo } from "../../storage/docStore/types";
import {
StorageContext,
storageContextFromDefaults,
} from "../../storage/StorageContext";
import { BaseDocumentStore, RefDocInfo } from "../../storage/docStore/types";
import {
BaseIndex,
BaseIndexInit,
@@ -32,11 +32,7 @@ export class VectorIndexRetriever implements BaseRetriever {
this.similarityTopK = similarityTopK ?? DEFAULT_SIMILARITY_TOP_K;
}
async retrieve(
query: string,
parentEvent?: Event,
preFilters?: unknown,
): Promise<NodeWithScore[]> {
async retrieve(query: string, parentEvent?: Event, preFilters?: unknown): Promise<NodeWithScore[]> {
const queryEmbedding =
await this.serviceContext.embedModel.getQueryEmbedding(query);
+13 -38
View File
@@ -377,10 +377,10 @@ export const ALL_AVAILABLE_LLAMADEUCE_MODELS = {
"Llama-2-70b-chat-4bit": {
contextWindow: 4096,
replicateApi:
"meta/llama-2-70b-chat:02e509c789964a7ea8736978a43525956ef40397be9033abf9fd2badfe68c9e3",
"replicate/llama70b-v2-chat:2c1608e18606fad2812020dc541930f2d0495ce32eee50074220b87300bc16e1",
//^ Model is based off of exllama 4bit.
},
"Llama-2-13b-chat-old": {
"Llama-2-13b-chat": {
contextWindow: 4096,
replicateApi:
"a16z-infra/llama13b-v2-chat:df7690f1994d94e96ad9d568eac121aecf50684a0b0963b25a41cc40061269e5",
@@ -389,9 +389,9 @@ export const ALL_AVAILABLE_LLAMADEUCE_MODELS = {
"Llama-2-13b-chat-4bit": {
contextWindow: 4096,
replicateApi:
"meta/llama-2-13b-chat:f4e2de70d66816a838a89eeeb621910adffb0dd0baba3976c96980970978018d",
"a16z-infra/llama13b-v2-chat:2a7f981751ec7fdf87b5b91ad4db53683a98082e9ff7bfd12c8cd5ea85980a52",
},
"Llama-2-7b-chat-old": {
"Llama-2-7b-chat": {
contextWindow: 4096,
replicateApi:
"a16z-infra/llama7b-v2-chat:4f0a4744c7295c024a1de15e1a63c880d3da035fa1f49bfd344fe076074c8eea",
@@ -403,7 +403,7 @@ export const ALL_AVAILABLE_LLAMADEUCE_MODELS = {
"Llama-2-7b-chat-4bit": {
contextWindow: 4096,
replicateApi:
"meta/llama-2-7b-chat:13c3cdee13ee059ab779f0291d29054dab00a47dad8261375654de5540165fb0",
"a16z-infra/llama7b-v2-chat:4f0b260b6a13eb53a6b1891f089d57c08f41003ae79458be5011303d81a394dc",
},
};
@@ -415,8 +415,6 @@ export enum DeuceChatStrategy {
// Unfortunately any string only API won't support these properly.
REPLICATE4BIT = "replicate4bit",
//^ To satisfy Replicate's 4 bit models' requirements where they also insert some INST tags
REPLICATE4BITWNEWLINES = "replicate4bitwnewlines",
//^ Replicate's documentation recommends using newlines: https://replicate.com/blog/how-to-prompt-llama
}
/**
@@ -436,7 +434,7 @@ export class LlamaDeuce implements LLM {
this.chatStrategy =
init?.chatStrategy ??
(this.model.endsWith("4bit")
? DeuceChatStrategy.REPLICATE4BITWNEWLINES // With the newer Replicate models they do the system message themselves.
? DeuceChatStrategy.REPLICATE4BIT // With the newer A16Z/Replicate models they do the system message themselves.
: DeuceChatStrategy.METAWBOS); // With BOS and EOS seems to work best, although they all have problems past a certain point
this.temperature = init?.temperature ?? 0.1; // minimum temperature is 0.01 for Replicate endpoint
this.topP = init?.topP ?? 1;
@@ -470,15 +468,7 @@ export class LlamaDeuce implements LLM {
} else if (this.chatStrategy === DeuceChatStrategy.METAWBOS) {
return this.mapMessagesToPromptMeta(messages, { withBos: true });
} else if (this.chatStrategy === DeuceChatStrategy.REPLICATE4BIT) {
return this.mapMessagesToPromptMeta(messages, {
replicate4Bit: true,
withNewlines: true,
});
} else if (this.chatStrategy === DeuceChatStrategy.REPLICATE4BITWNEWLINES) {
return this.mapMessagesToPromptMeta(messages, {
replicate4Bit: true,
withNewlines: true,
});
return this.mapMessagesToPromptMeta(messages, { replicate4Bit: true });
} else {
return this.mapMessagesToPromptMeta(messages);
}
@@ -513,17 +503,9 @@ export class LlamaDeuce implements LLM {
mapMessagesToPromptMeta(
messages: ChatMessage[],
opts?: {
withBos?: boolean;
replicate4Bit?: boolean;
withNewlines?: boolean;
},
opts?: { withBos?: boolean; replicate4Bit?: boolean },
) {
const {
withBos = false,
replicate4Bit = false,
withNewlines = false,
} = opts ?? {};
const { withBos = false, replicate4Bit = false } = opts ?? {};
const DEFAULT_SYSTEM_PROMPT = `You are a helpful, respectful and honest assistant. Always answer as helpfully as possible, while being safe. Your answers should not include any harmful, unethical, racist, sexist, toxic, dangerous, or illegal content. Please ensure that your responses are socially unbiased and positive in nature.
If a question does not make any sense, or is not factually coherent, explain why instead of answering something not correct. If you don't know the answer to a question, please don't share false information.`;
@@ -571,18 +553,11 @@ If a question does not make any sense, or is not factually coherent, explain why
return {
prompt: messages.reduce((acc, message, index) => {
if (index % 2 === 0) {
return (
`${acc}${
withBos ? BOS : ""
}${B_INST} ${message.content.trim()} ${E_INST}` +
(withNewlines ? "\n" : "")
);
return `${acc}${
withBos ? BOS : ""
}${B_INST} ${message.content.trim()} ${E_INST}`;
} else {
return (
`${acc} ${message.content.trim()}` +
(withNewlines ? "\n" : " ") +
(withBos ? EOS : "")
); // Yes, the EOS comes after the space. This is not a mistake.
return `${acc} ${message.content.trim()} ` + (withBos ? EOS : ""); // Yes, the EOS comes after the space. This is not a mistake.
}
}, ""),
systemPrompt,
+9 -11
View File
@@ -1,12 +1,9 @@
import _ from "lodash";
import { LLMOptions, Portkey } from "portkey-ai";
export const readEnv = (
env: string,
default_val?: string,
): string | undefined => {
if (typeof process !== "undefined") {
return process.env?.[env] ?? default_val;
export const readEnv = (env: string, default_val?: string): string | undefined => {
if (typeof process !== 'undefined') {
return process.env?.[env] ?? default_val;
}
return default_val;
};
@@ -15,23 +12,23 @@ interface PortkeyOptions {
apiKey?: string;
baseURL?: string;
mode?: string;
llms?: [LLMOptions] | null;
llms?: [LLMOptions] | null
}
export class PortkeySession {
portkey: Portkey;
constructor(options: PortkeyOptions = {}) {
constructor(options:PortkeyOptions = {}) {
if (!options.apiKey) {
options.apiKey = readEnv("PORTKEY_API_KEY");
options.apiKey = readEnv('PORTKEY_API_KEY')
}
if (!options.baseURL) {
options.baseURL = readEnv("PORTKEY_BASE_URL", "https://api.portkey.ai");
options.baseURL = readEnv('PORTKEY_BASE_URL', "https://api.portkey.ai")
}
this.portkey = new Portkey({});
this.portkey.llms = [{}];
this.portkey.llms = [{}]
if (!options.apiKey) {
throw new Error("Set Portkey ApiKey in PORTKEY_API_KEY env variable");
}
@@ -62,3 +59,4 @@ export function getPortkeySession(options: PortkeyOptions = {}) {
}
return session;
}
+1 -1
View File
@@ -1,7 +1,7 @@
import mammoth from "mammoth";
import { Document } from "../Node";
import { GenericFileSystem } from "../storage/FileSystem";
import { DEFAULT_FS } from "../storage/constants";
import { GenericFileSystem } from "../storage/FileSystem";
import { BaseReader } from "./base";
export class DocxReader implements BaseReader {
-6
View File
@@ -1,11 +1,5 @@
# create-llama
## 0.0.5
### Patch Changes
- 25257f4: Fix issue where it doesn't find OpenAI Key when running npm run generate (#182) (thanks @RayFernando1337)
## 0.0.4
### Patch Changes
-9
View File
@@ -1,9 +0,0 @@
The MIT License (MIT)
Copyright (c) 2023 LlamaIndex, Vercel, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+7 -8
View File
@@ -1,6 +1,6 @@
# Create LlamaIndex App
The easiest way to get started with [LlamaIndex](https://www.llamaindex.ai/) is by using `create-llama`. This CLI tool enables you to quickly start building a new LlamaIndex application, with everything set up for you.
The easiest way to get started with [LlamaIndex](https://www.llamaindex.ai/) is by using `create-llama`. This CLI tool enables you to quickly start building a new LlamaIndex application, with everything set up for you.
## Features
@@ -19,11 +19,11 @@ You can create a new project interactively by running:
```bash
npx create-llama@latest
# or
npm create llama@latest
npm create llama
# or
yarn create llama
# or
pnpm create llama@latest
pnpm create llama
```
You will be asked for the name of your project, along with other configuration options.
@@ -31,16 +31,16 @@ You will be asked for the name of your project, along with other configuration o
Here is an example:
```bash
>> npm create llama@latest
>> npm create llama
Need to install the following packages:
create-llama@latest
create-llama@0.0.3
Ok to proceed? (y) y
✔ What is your project named? … my-app
✔ Which template would you like to use? Chat with streaming
✔ Which framework would you like to use? NextJS
✔ Which UI would you like to use? Just HTML
✔ Which chat engine would you like to use? ContextChatEngine
✔ Please provide your OpenAI API key (leave blank to skip): …
✔ Please provide your OpenAI API key (leave blank to skip): …
✔ Would you like to use ESLint? … No / Yes
Creating a new LlamaIndex app in /home/my-app.
```
@@ -55,6 +55,7 @@ create-llama <project-directory> [options]
Options:
-V, --version output the version number
--use-npm
@@ -74,5 +75,3 @@ Options:
- [TS/JS docs](https://ts.llamaindex.ai/)
- [Python docs](https://docs.llamaindex.ai/en/stable/)
Inspired by and adapted from [create-next-app](https://github.com/vercel/next.js/tree/canary/packages/create-next-app)
+1 -1
View File
@@ -43,7 +43,7 @@ export function tryGitInit(root: string): boolean {
}
execSync("git add -A", { stdio: "ignore" });
execSync('git commit -m "Initial commit from Create Llama"', {
execSync('git commit -m "Initial commit from Create Next App"', {
stdio: "ignore",
});
return true;
+10 -13
View File
@@ -79,10 +79,10 @@ const program = new Commander.Command(packageJson.name)
const packageManager = !!program.useNpm
? "npm"
: !!program.usePnpm
? "pnpm"
: !!program.useYarn
? "yarn"
: getPkgManager();
? "pnpm"
: !!program.useYarn
? "yarn"
: getPkgManager();
async function run(): Promise<void> {
const conf = new Conf({ projectName: "create-llama" });
@@ -235,8 +235,8 @@ async function run(): Promise<void> {
program.framework === "express"
? "Express "
: program.framework === "fastapi"
? "FastAPI (Python) "
: "",
? "FastAPI (Python) "
: "",
);
const { frontend } = await prompts({
onState: onPromptState,
@@ -288,11 +288,8 @@ async function run(): Promise<void> {
name: "engine",
message: "Which chat engine would you like to use?",
choices: [
{ title: "SimpleChatEngine", value: "simple" },
{ title: "ContextChatEngine", value: "context" },
{
title: "SimpleChatEngine (no data, just chat)",
value: "simple",
},
],
initial: 0,
},
@@ -362,10 +359,10 @@ async function notifyUpdate(): Promise<void> {
if (res?.latest) {
const updateMessage =
packageManager === "yarn"
? "yarn global add create-llama@latest"
? "yarn global add create-llama"
: packageManager === "pnpm"
? "pnpm add -g create-llama@latest"
: "npm i -g create-llama@latest";
? "pnpm add -g create-llama"
: "npm i -g create-llama";
console.log(
yellow(bold("A new version of `create-llama` is available!")) +
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "create-llama",
"version": "0.0.5",
"version": "0.0.4",
"keywords": [
"rag",
"llamaindex",
@@ -1,23 +1,23 @@
"use client";
"use client"
import { Check, Copy, Download } from "lucide-react";
import { FC, memo } from "react";
import { Prism, SyntaxHighlighterProps } from "react-syntax-highlighter";
import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism";
import React, { FC, memo } from "react"
import { Check, Copy, Download } from "lucide-react"
import { Prism, SyntaxHighlighterProps } from "react-syntax-highlighter"
import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism"
import { Button } from "../button";
import { useCopyToClipboard } from "./use-copy-to-clipboard";
import { Button } from "../button"
import { useCopyToClipboard } from "./use-copy-to-clipboard"
// TODO: Remove this when @type/react-syntax-highlighter is updated
const SyntaxHighlighter = Prism as unknown as FC<SyntaxHighlighterProps>;
const SyntaxHighlighter = Prism as unknown as FC<SyntaxHighlighterProps>
interface Props {
language: string;
value: string;
language: string
value: string
}
interface languageMap {
[key: string]: string | undefined;
[key: string]: string | undefined
}
export const programmingLanguages: languageMap = {
@@ -45,52 +45,52 @@ export const programmingLanguages: languageMap = {
html: ".html",
css: ".css",
// add more file extensions here, make sure the key is same as language prop in CodeBlock.tsx component
};
}
export const generateRandomString = (length: number, lowercase = false) => {
const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789"; // excluding similar looking characters like Z, 2, I, 1, O, 0
let result = "";
const chars = "ABCDEFGHJKLMNPQRSTUVWXY3456789" // excluding similar looking characters like Z, 2, I, 1, O, 0
let result = ""
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length));
result += chars.charAt(Math.floor(Math.random() * chars.length))
}
return lowercase ? result.toLowerCase() : result;
};
return lowercase ? result.toLowerCase() : result
}
const CodeBlock: FC<Props> = memo(({ language, value }) => {
const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 });
const { isCopied, copyToClipboard } = useCopyToClipboard({ timeout: 2000 })
const downloadAsFile = () => {
if (typeof window === "undefined") {
return;
return
}
const fileExtension = programmingLanguages[language] || ".file";
const fileExtension = programmingLanguages[language] || ".file"
const suggestedFileName = `file-${generateRandomString(
3,
true,
)}${fileExtension}`;
const fileName = window.prompt("Enter file name" || "", suggestedFileName);
true
)}${fileExtension}`
const fileName = window.prompt("Enter file name" || "", suggestedFileName)
if (!fileName) {
// User pressed cancel on prompt.
return;
return
}
const blob = new Blob([value], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const link = document.createElement("a");
link.download = fileName;
link.href = url;
link.style.display = "none";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
};
const blob = new Blob([value], { type: "text/plain" })
const url = URL.createObjectURL(blob)
const link = document.createElement("a")
link.download = fileName
link.href = url
link.style.display = "none"
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
}
const onCopy = () => {
if (isCopied) return;
copyToClipboard(value);
};
if (isCopied) return
copyToClipboard(value)
}
return (
<div className="codeblock relative w-full bg-zinc-950 font-sans">
@@ -132,8 +132,8 @@ const CodeBlock: FC<Props> = memo(({ language, value }) => {
{value}
</SyntaxHighlighter>
</div>
);
});
CodeBlock.displayName = "CodeBlock";
)
})
CodeBlock.displayName = "CodeBlock"
export { CodeBlock };
export { CodeBlock }
@@ -2,4 +2,4 @@ import ChatInput from "./chat-input";
import ChatMessages from "./chat-messages";
export { type ChatHandler, type Message } from "./chat.interface";
export { ChatInput, ChatMessages };
export { ChatMessages, ChatInput };
@@ -1,16 +1,16 @@
import { FC, memo } from "react";
import ReactMarkdown, { Options } from "react-markdown";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import { FC, memo } from "react"
import ReactMarkdown, { Options } from "react-markdown"
import remarkGfm from "remark-gfm"
import remarkMath from "remark-math"
import { CodeBlock } from "./codeblock";
import { CodeBlock } from "./codeblock"
const MemoizedReactMarkdown: FC<Options> = memo(
ReactMarkdown,
(prevProps, nextProps) =>
prevProps.children === nextProps.children &&
prevProps.className === nextProps.className,
);
prevProps.className === nextProps.className
)
export default function Markdown({ content }: { content: string }) {
return (
@@ -19,27 +19,27 @@ export default function Markdown({ content }: { content: string }) {
remarkPlugins={[remarkGfm, remarkMath]}
components={{
p({ children }) {
return <p className="mb-2 last:mb-0">{children}</p>;
return <p className="mb-2 last:mb-0">{children}</p>
},
code({ node, inline, className, children, ...props }) {
if (children.length) {
if (children[0] == "▍") {
return (
<span className="mt-1 animate-pulse cursor-default"></span>
);
)
}
children[0] = (children[0] as string).replace("`▍`", "▍");
children[0] = (children[0] as string).replace("`▍`", "▍")
}
const match = /language-(\w+)/.exec(className || "");
const match = /language-(\w+)/.exec(className || "")
if (inline) {
return (
<code className={className} {...props}>
{children}
</code>
);
)
}
return (
@@ -49,11 +49,11 @@ export default function Markdown({ content }: { content: string }) {
value={String(children).replace(/\n$/, "")}
{...props}
/>
);
)
},
}}
>
{content}
</MemoizedReactMarkdown>
);
)
}
@@ -1,33 +1,33 @@
"use client";
'use client'
import * as React from "react";
import * as React from 'react'
export interface useCopyToClipboardProps {
timeout?: number;
timeout?: number
}
export function useCopyToClipboard({
timeout = 2000,
timeout = 2000
}: useCopyToClipboardProps) {
const [isCopied, setIsCopied] = React.useState<Boolean>(false);
const [isCopied, setIsCopied] = React.useState<Boolean>(false)
const copyToClipboard = (value: string) => {
if (typeof window === "undefined" || !navigator.clipboard?.writeText) {
return;
if (typeof window === 'undefined' || !navigator.clipboard?.writeText) {
return
}
if (!value) {
return;
return
}
navigator.clipboard.writeText(value).then(() => {
setIsCopied(true);
setIsCopied(true)
setTimeout(() => {
setIsCopied(false);
}, timeout);
});
};
setIsCopied(false)
}, timeout)
})
}
return { isCopied, copyToClipboard };
return { isCopied, copyToClipboard }
}
+5 -16
View File
@@ -33,7 +33,6 @@ const createEnvLocalFile = async (
`OPENAI_API_KEY=${openAIKey}\n`,
);
console.log(`Created '${envFileName}' file containing OPENAI_API_KEY`);
process.env["OPENAI_API_KEY"] = openAIKey;
}
};
@@ -54,21 +53,11 @@ const copyTestData = async (
}
if (packageManager && engine === "context") {
if (process.env["OPENAI_API_KEY"]) {
console.log(
`\nRunning ${cyan(
`${packageManager} run generate`,
)} to generate the context data.\n`,
);
await callPackageManager(packageManager, true, ["run", "generate"]);
console.log();
} else {
console.log(
`\nAfter setting your OpenAI key, run ${cyan(
`${packageManager} run generate`,
)} to generate the context data.\n`,
);
}
console.log(
`\nRunning ${cyan("npm run generate")} to generate the context data.\n`,
);
await callPackageManager(packageManager, true, ["run", "generate"]);
console.log();
}
};
@@ -3,4 +3,4 @@ import ChatMessages from "./chat-messages";
export type { ChatInputProps } from "./chat-input";
export type { Message } from "./chat-messages";
export { ChatInput, ChatMessages };
export { ChatMessages, ChatInput };
@@ -1,8 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
serverComponentsExternalPackages: ["llamaindex"],
},
};
serverComponentsExternalPackages: ["llamaindex"],
},
}
module.exports = nextConfig;
module.exports = nextConfig
@@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {},
autoprefixer: {},
},
};
}
@@ -3,4 +3,4 @@ import ChatMessages from "./chat-messages";
export type { ChatInputProps } from "./chat-input";
export type { Message } from "./chat-messages";
export { ChatInput, ChatMessages };
export { ChatMessages, ChatInput };
@@ -1,8 +1,8 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
serverComponentsExternalPackages: ["llamaindex"],
},
};
serverComponentsExternalPackages: ["llamaindex"],
},
}
module.exports = nextConfig;
module.exports = nextConfig
@@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {},
autoprefixer: {},
},
};
}
+518 -714
View File
File diff suppressed because it is too large Load Diff