Compare commits

...

33 Commits

Author SHA1 Message Date
sweep-ai[bot] f3cb5c60c4 feat: Updated packages/create-llama/templates/type 2024-01-10 13:12:40 +00:00
sweep-ai[bot] c98743243e feat: Updated packages/create-llama/templates/type 2024-01-10 13:12:23 +00:00
sweep-ai[bot] 0cfcb5c941 feat: Updated packages/create-llama/templates/type 2024-01-10 13:11:49 +00:00
sweep-ai[bot] c712e07069 feat: Updated packages/create-llama/templates/type 2024-01-10 12:59:02 +00:00
sweep-ai[bot] df64020820 feat: Updated packages/create-llama/templates/type 2024-01-10 12:56:04 +00:00
sweep-ai[bot] 6e95129b0c feat: Updated packages/create-llama/templates/type 2024-01-10 12:55:39 +00:00
sweep-ai[bot] 6816d94407 feat: Updated packages/core/src/tests/Embedding.te 2024-01-10 12:51:25 +00:00
sweep-ai[bot] 6d340b61c2 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:51:06 +00:00
sweep-ai[bot] 9b2db81e57 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:48:02 +00:00
sweep-ai[bot] 84b0b067f7 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:46:03 +00:00
sweep-ai[bot] 0720cd4f7b feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:45:44 +00:00
sweep-ai[bot] 84545e3ed9 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:44:33 +00:00
sweep-ai[bot] a18d714aa5 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:44:09 +00:00
sweep-ai[bot] 64e9be0b9b feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:43:35 +00:00
sweep-ai[bot] 3525f01fb9 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:43:21 +00:00
sweep-ai[bot] 0f7aeebc7e feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:43:02 +00:00
sweep-ai[bot] 4dd3501db8 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:42:48 +00:00
sweep-ai[bot] 22d6f4dd99 feat: Updated .github/workflows/e2e.yml 2024-01-10 12:37:06 +00:00
sweep-ai[bot] 58d9cf0b7e feat: Updated packages/create-llama/templates/type 2024-01-10 12:33:49 +00:00
sweep-ai[bot] 98802f8c92 feat: Updated packages/core/src/tests/Embedding.te 2024-01-10 12:30:44 +00:00
sweep-ai[bot] c83c2b2d70 feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 12:28:25 +00:00
sweep-ai[bot] c311787961 feat: Updated packages/create-llama/templates/type 2024-01-10 12:19:28 +00:00
sweep-ai[bot] 2ba629c063 feat: Updated packages/create-llama/templates/type 2024-01-10 12:19:11 +00:00
sweep-ai[bot] 34c5c98797 feat: Updated packages/core/src/llm/openai.ts 2024-01-10 12:16:15 +00:00
sweep-ai[bot] 96c3044a03 feat: Updated packages/core/src/llm/mistral.ts 2024-01-10 12:15:56 +00:00
sweep-ai[bot] a31b867f17 feat: Updated packages/core/src/llm/mistral.ts 2024-01-10 11:57:05 +00:00
sweep-ai[bot] 86fbb41e85 feat: Updated packages/core/src/llm/mistral.ts 2024-01-10 11:56:50 +00:00
sweep-ai[bot] 5fc5e83e4a feat: Updated packages/core/src/llm/mistral.ts 2024-01-10 11:50:38 +00:00
sweep-ai[bot] d16756c850 feat: Updated packages/core/src/llm/mistral.ts 2024-01-10 11:37:55 +00:00
sweep-ai[bot] a3b9a6d2fb feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 11:37:41 +00:00
sweep-ai[bot] 360819c2df feat: Updated packages/core/src/tests/CallbackMana 2024-01-10 11:20:49 +00:00
sweep-ai[bot] 561a06f182 feat: Updated packages/core/src/llm/mistral.ts 2024-01-10 11:18:27 +00:00
Marcus Schiesser f7d4e52fe2 refactor: change contract of LLM.ts 2024-01-10 18:10:54 +07:00
12 changed files with 198 additions and 201 deletions
+6 -1
View File
@@ -8,6 +8,10 @@ on:
- ".github/workflows/e2e.yml"
branches: [main]
env:
CI:
secrete: ''
PLAYWRIGHT_BROWSERS_PATH: './packages/create-llama/playwright-report/'
jobs:
e2e:
name: create-llama
@@ -35,7 +39,7 @@ jobs:
run: pnpm run build
working-directory: ./packages/create-llama
- name: Run Playwright tests
run: pnpm exec playwright test
run: pnpm exec playwright test 2>&1 | tee error_logs.txt
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
working-directory: ./packages/create-llama
@@ -44,4 +48,5 @@ jobs:
with:
name: playwright-report
path: ./packages/create-llama/playwright-report/
- ./error_logs.txt
retention-days: 30
+124 -161
View File
@@ -10,7 +10,6 @@ import {
import { ChatCompletionMessageParam } from "openai/resources";
import { LLMOptions } from "portkey-ai";
import { MessageContent } from "../ChatEngine";
import { globalsHelper, Tokenizers } from "../GlobalsHelper";
import {
ANTHROPIC_AI_PROMPT,
@@ -48,8 +47,9 @@ export interface ChatResponse {
delta?: string;
}
// NOTE in case we need CompletionResponse to diverge from ChatResponse in the future
export type CompletionResponse = ChatResponse;
export interface CompletionResponse {
text: string;
}
export interface LLMMetadata {
model: string;
@@ -60,40 +60,57 @@ export interface LLMMetadata {
tokenizer: Tokenizers | undefined;
}
export interface LLMChatParamsBase {
messages: ChatMessage[];
parentEvent?: Event;
extraParams?: Record<string, any>;
}
export interface LLMChatParamsStreaming extends LLMChatParamsBase {
stream: true;
}
export interface LLMChatParamsNonStreaming extends LLMChatParamsBase {
stream?: false | null;
}
export interface LLMCompletionParamsBase {
prompt: string;
parentEvent?: Event;
}
export interface LLMCompletionParamsStreaming extends LLMCompletionParamsBase {
stream: true;
}
export interface LLMCompletionParamsNonStreaming
extends LLMCompletionParamsBase {
stream?: false | null;
}
/**
* Unified language model interface
*/
export interface LLM {
metadata: LLMMetadata;
// Whether a LLM has streaming support
hasStreaming: boolean;
/**
* Get a chat response from the LLM
* @param messages
*
* The return type of chat() and complete() are set by the "streaming" parameter being set to True.
* @param params
*/
chat<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(
messages: ChatMessage[],
parentEvent?: Event,
streaming?: T,
): Promise<R>;
chat(params: LLMChatParamsStreaming): Promise<AsyncIterable<string>>;
chat(params: LLMChatParamsNonStreaming): Promise<ChatResponse>;
/**
* Get a prompt completion from the LLM
* @param prompt the prompt to complete
* @param params
*/
complete<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(
prompt: MessageContent,
parentEvent?: Event,
streaming?: T,
): Promise<R>;
complete(
params: LLMCompletionParamsStreaming,
): Promise<AsyncIterable<string>>;
complete(
params: LLMCompletionParamsNonStreaming,
): Promise<CompletionResponse>;
/**
* Calculates the number of tokens needed for the given chat messages
@@ -101,6 +118,39 @@ export interface LLM {
tokens(messages: ChatMessage[]): number;
}
abstract class BaseLLM implements LLM {
abstract metadata: LLMMetadata;
complete(
params: LLMCompletionParamsStreaming,
): Promise<AsyncIterable<string>>;
complete(
params: LLMCompletionParamsNonStreaming,
): Promise<CompletionResponse>;
async complete(
params: LLMCompletionParamsStreaming | LLMCompletionParamsNonStreaming,
): Promise<CompletionResponse | AsyncIterable<string>> {
const { prompt, parentEvent, stream } = params;
if (stream) {
return this.chat({
messages: [{ content: prompt, role: "user" }],
parentEvent,
stream: true,
});
}
const chatResponse = await this.chat({
messages: [{ content: prompt, role: "user" }],
parentEvent,
});
return { text: chatResponse.message.content as string };
}
abstract chat(params: LLMChatParamsStreaming): Promise<AsyncIterable<string>>;
abstract chat(params: LLMChatParamsNonStreaming): Promise<ChatResponse>;
abstract tokens(messages: ChatMessage[]): number;
}
export const GPT4_MODELS = {
"gpt-4": { contextWindow: 8192 },
"gpt-4-32k": { contextWindow: 32768 },
@@ -125,9 +175,7 @@ export const ALL_AVAILABLE_OPENAI_MODELS = {
/**
* OpenAI LLM implementation
*/
export class OpenAI implements LLM {
hasStreaming: boolean = true;
export class OpenAI extends BaseLLM {
// Per completion OpenAI params
model: keyof typeof ALL_AVAILABLE_OPENAI_MODELS;
temperature: number;
@@ -135,7 +183,7 @@ export class OpenAI implements LLM {
maxTokens?: number;
additionalChatOptions?: Omit<
Partial<OpenAILLM.Chat.ChatCompletionCreateParams>,
"max_tokens" | "messages" | "model" | "temperature" | "top_p" | "streaming"
"max_tokens" | "messages" | "model" | "temperature" | "top_p" | "stream"
>;
// OpenAI session params
@@ -155,6 +203,7 @@ export class OpenAI implements LLM {
azure?: AzureOpenAIConfig;
},
) {
super();
this.model = init?.model ?? "gpt-3.5-turbo";
this.temperature = init?.temperature ?? 0.1;
this.topP = init?.topP ?? 1;
@@ -247,10 +296,12 @@ export class OpenAI implements LLM {
}
}
async chat<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(messages: ChatMessage[], parentEvent?: Event, streaming?: T): Promise<R> {
chat(params: LLMChatParamsStreaming): Promise<AsyncIterable<string>>;
chat(params: LLMChatParamsNonStreaming): Promise<ChatResponse>;
async chat(
params: LLMChatParamsNonStreaming | LLMChatParamsStreaming,
): Promise<ChatResponse | AsyncIterable<string>> {
const { messages, parentEvent, stream } = params;
const baseRequestParams: OpenAILLM.Chat.ChatCompletionCreateParams = {
model: this.model,
temperature: this.temperature,
@@ -266,11 +317,8 @@ export class OpenAI implements LLM {
...this.additionalChatOptions,
};
// Streaming
if (streaming) {
if (!this.hasStreaming) {
throw Error("No streaming support for this LLM.");
}
return this.streamChat(messages, parentEvent) as R;
if (stream) {
return this.streamChat(params);
}
// Non-streaming
const response = await this.session.openai.chat.completions.create({
@@ -281,27 +329,13 @@ export class OpenAI implements LLM {
const content = response.choices[0].message?.content ?? "";
return {
message: { content, role: response.choices[0].message.role },
} as R;
};
}
async complete<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(prompt: string, parentEvent?: Event, streaming?: T): Promise<R> {
return this.chat(
[{ content: prompt, role: "user" }],
parentEvent,
streaming,
);
}
//We can wrap a stream in a generator to add some additional logging behavior
//For future edits: syntax for generator type is <typeof Yield, typeof Return, typeof Accept>
//"typeof Accept" refers to what types you'll accept when you manually call generator.next(<AcceptType>)
protected async *streamChat(
messages: ChatMessage[],
parentEvent?: Event,
): AsyncGenerator<string, void, unknown> {
protected async *streamChat({
messages,
parentEvent,
}: LLMChatParamsStreaming): AsyncIterable<string> {
const baseRequestParams: OpenAILLM.Chat.ChatCompletionCreateParams = {
model: this.model,
temperature: this.temperature,
@@ -360,14 +394,6 @@ export class OpenAI implements LLM {
}
return;
}
//streamComplete doesn't need to be async because it's child function is already async
protected streamComplete(
query: string,
parentEvent?: Event,
): AsyncGenerator<string, void, unknown> {
return this.streamChat([{ content: query, role: "user" }], parentEvent);
}
}
export const ALL_AVAILABLE_LLAMADEUCE_MODELS = {
@@ -425,16 +451,16 @@ export enum DeuceChatStrategy {
/**
* Llama2 LLM implementation
*/
export class LlamaDeuce implements LLM {
export class LlamaDeuce extends BaseLLM {
model: keyof typeof ALL_AVAILABLE_LLAMADEUCE_MODELS;
chatStrategy: DeuceChatStrategy;
temperature: number;
topP: number;
maxTokens?: number;
replicateSession: ReplicateSession;
hasStreaming: boolean;
constructor(init?: Partial<LlamaDeuce>) {
super();
this.model = init?.model ?? "Llama-2-70b-chat-4bit";
this.chatStrategy =
init?.chatStrategy ??
@@ -447,7 +473,6 @@ export class LlamaDeuce implements LLM {
init?.maxTokens ??
ALL_AVAILABLE_LLAMADEUCE_MODELS[this.model].contextWindow; // For Replicate, the default is 500 tokens which is too low.
this.replicateSession = init?.replicateSession ?? new ReplicateSession();
this.hasStreaming = init?.hasStreaming ?? false;
}
tokens(messages: ChatMessage[]): number {
@@ -592,10 +617,12 @@ If a question does not make any sense, or is not factually coherent, explain why
};
}
async chat<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(messages: ChatMessage[], _parentEvent?: Event, streaming?: T): Promise<R> {
chat(params: LLMChatParamsStreaming): Promise<AsyncIterable<string>>;
chat(params: LLMChatParamsNonStreaming): Promise<ChatResponse>;
async chat(
params: LLMChatParamsNonStreaming | LLMChatParamsStreaming,
): Promise<ChatResponse | AsyncIterable<string>> {
const { messages, parentEvent, stream } = params;
const api = ALL_AVAILABLE_LLAMADEUCE_MODELS[this.model]
.replicateApi as `${string}/${string}:${string}`;
@@ -629,14 +656,7 @@ If a question does not make any sense, or is not factually coherent, explain why
//^ We need to do this because Replicate returns a list of strings (for streaming functionality which is not exposed by the run function)
role: "assistant",
},
} as R;
}
async complete<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(prompt: string, parentEvent?: Event, streaming?: T): Promise<R> {
return this.chat([{ content: prompt, role: "user" }], parentEvent);
};
}
}
@@ -650,9 +670,7 @@ export const ALL_AVAILABLE_ANTHROPIC_MODELS = {
* Anthropic LLM implementation
*/
export class Anthropic implements LLM {
hasStreaming: boolean = true;
export class Anthropic extends BaseLLM {
// Per completion Anthropic params
model: keyof typeof ALL_AVAILABLE_ANTHROPIC_MODELS;
temperature: number;
@@ -668,6 +686,7 @@ export class Anthropic implements LLM {
callbackManager?: CallbackManager;
constructor(init?: Partial<Anthropic>) {
super();
this.model = init?.model ?? "claude-2";
this.temperature = init?.temperature ?? 0.1;
this.topP = init?.topP ?? 0.999; // Per Ben Mann
@@ -719,20 +738,15 @@ export class Anthropic implements LLM {
);
}
async chat<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(
messages: ChatMessage[],
parentEvent?: Event | undefined,
streaming?: T,
): Promise<R> {
chat(params: LLMChatParamsStreaming): Promise<AsyncIterable<string>>;
chat(params: LLMChatParamsNonStreaming): Promise<ChatResponse>;
async chat(
params: LLMChatParamsNonStreaming | LLMChatParamsStreaming,
): Promise<ChatResponse | AsyncIterable<string>> {
const { messages, parentEvent, stream } = params;
//Streaming
if (streaming) {
if (!this.hasStreaming) {
throw Error("No streaming support for this LLM.");
}
return this.streamChat(messages, parentEvent) as R;
if (stream) {
return this.streamChat(messages, parentEvent);
}
//Non-streaming
@@ -748,13 +762,13 @@ export class Anthropic implements LLM {
message: { content: response.completion.trimStart(), role: "assistant" },
//^ We're trimming the start because Anthropic often starts with a space in the response
// That space will be re-added when we generate the next prompt.
} as R;
};
}
protected async *streamChat(
messages: ChatMessage[],
parentEvent?: Event | undefined,
): AsyncGenerator<string, void, unknown> {
): AsyncIterable<string> {
// AsyncIterable<AnthropicStreamToken>
const stream: AsyncIterable<AnthropicStreamToken> =
await this.session.anthropic.completions.create({
@@ -775,36 +789,9 @@ export class Anthropic implements LLM {
}
return;
}
async complete<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(
prompt: string,
parentEvent?: Event | undefined,
streaming?: T,
): Promise<R> {
if (streaming) {
return this.streamComplete(prompt, parentEvent) as R;
}
return this.chat(
[{ content: prompt, role: "user" }],
parentEvent,
streaming,
) as R;
}
protected streamComplete(
prompt: string,
parentEvent?: Event | undefined,
): AsyncGenerator<string, void, unknown> {
return this.streamChat([{ content: prompt, role: "user" }], parentEvent);
}
}
export class Portkey implements LLM {
hasStreaming: boolean = true;
export class Portkey extends BaseLLM {
apiKey?: string = undefined;
baseURL?: string = undefined;
mode?: string = undefined;
@@ -813,6 +800,7 @@ export class Portkey implements LLM {
callbackManager?: CallbackManager;
constructor(init?: Partial<Portkey>) {
super();
this.apiKey = init?.apiKey;
this.baseURL = init?.baseURL;
this.mode = init?.mode;
@@ -834,45 +822,27 @@ export class Portkey implements LLM {
throw new Error("metadata not implemented for Portkey");
}
async chat<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(
messages: ChatMessage[],
parentEvent?: Event | undefined,
streaming?: T,
params?: Record<string, any>,
): Promise<R> {
if (streaming) {
return this.streamChat(messages, parentEvent, params) as R;
chat(params: LLMChatParamsStreaming): Promise<AsyncIterable<string>>;
chat(params: LLMChatParamsNonStreaming): Promise<ChatResponse>;
async chat(
params: LLMChatParamsNonStreaming | LLMChatParamsStreaming,
): Promise<ChatResponse | AsyncIterable<string>> {
const { messages, parentEvent, stream, extraParams } = params;
if (stream) {
return this.streamChat(messages, parentEvent, extraParams);
} else {
const resolvedParams = params || {};
const bodyParams = extraParams || {};
const response = await this.session.portkey.chatCompletions.create({
messages,
...resolvedParams,
...bodyParams,
});
const content = response.choices[0].message?.content ?? "";
const role = response.choices[0].message?.role || "assistant";
return { message: { content, role: role as MessageType } } as R;
return { message: { content, role: role as MessageType } };
}
}
async complete<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(
prompt: string,
parentEvent?: Event | undefined,
streaming?: T,
): Promise<R> {
return this.chat(
[{ content: prompt, role: "user" }],
parentEvent,
streaming,
);
}
async *streamChat(
messages: ChatMessage[],
parentEvent?: Event,
@@ -919,11 +889,4 @@ export class Portkey implements LLM {
}
return;
}
streamComplete(
query: string,
parentEvent?: Event,
): AsyncGenerator<string, void, unknown> {
return this.streamChat([{ content: query, role: "user" }], parentEvent);
}
}
+4 -10
View File
@@ -43,6 +43,7 @@ export class MistralAISession {
*/
export class MistralAI implements LLM {
hasStreaming: boolean = true;
// Per completion MistralAI params
model: keyof typeof ALL_AVAILABLE_MISTRAL_MODELS;
@@ -94,16 +95,13 @@ export class MistralAI implements LLM {
};
}
async chat<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(messages: ChatMessage[], parentEvent?: Event, streaming?: T): Promise<R> {
async chat(messages: ChatMessage[], parentEvent?: Event, streaming?: boolean): Promise<any> {
// Streaming
if (streaming) {
if (!this.hasStreaming) {
throw Error("No streaming support for this LLM.");
}
return this.streamChat(messages, parentEvent) as R;
return this.streamChat(messages, parentEvent) as any;
}
// Non-streaming
const client = await this.session.getClient();
@@ -114,10 +112,7 @@ export class MistralAI implements LLM {
} as R;
}
async complete<
T extends boolean | undefined = undefined,
R = T extends true ? AsyncGenerator<string, void, unknown> : ChatResponse,
>(prompt: string, parentEvent?: Event, streaming?: T): Promise<R> {
async complete(prompt: string, parentEvent?: Event, streaming?: boolean): Promise<ChatResponse> {
return this.chat(
[{ content: prompt, role: "user" }],
parentEvent,
@@ -148,7 +143,6 @@ export class MistralAI implements LLM {
var idx_counter: number = 0;
for await (const part of chunkStream) {
if (!part.choices.length) continue;
part.choices[0].index = idx_counter;
const isDone: boolean =
part.choices[0].finish_reason === "stop" ? true : false;
+2
View File
@@ -1,6 +1,8 @@
import _ from "lodash";
import OpenAI, { ClientOptions } from "openai";
export { OpenAI };
export class AzureOpenAI extends OpenAI {
protected override authHeaders() {
return { "api-key": this.apiKey };
+19 -10
View File
@@ -1,5 +1,5 @@
import { Document } from "../Node";
import { ServiceContext, serviceContextFromDefaults } from "../ServiceContext";
import {
CallbackManager,
RetrievalCallbackResponse,
@@ -8,9 +8,18 @@ import {
import { OpenAIEmbedding } from "../embeddings";
import { SummaryIndex } from "../indices/summary";
import { VectorStoreIndex } from "../indices/vectorStore/VectorStoreIndex";
import { OpenAI } from "../llm/LLM";
import { OpenAI, Event, ClientOptions } from "../llm/openai";
// Mock the OpenAI getOpenAISession function during testing
jest.mock("../llm/openai", () => {
return {
getOpenAISession: jest.fn().mockImplementation(() => null),
};
});
import { ResponseSynthesizer, SimpleResponseBuilder } from "../synthesizers";
import { mockEmbeddingModel, mockLlmGeneration } from "./utility/mockOpenAI";
// Mock the OpenAI getOpenAISession function during testing
jest.mock("../llm/openai", () => {
@@ -37,18 +46,18 @@ describe("CallbackManager: onLLMStream and onRetrieve", () => {
});
const languageModel = new OpenAI({
model: "gpt-3.5-turbo",
model: "davinci",
callbackManager,
});
mockLlmGeneration({ languageModel, callbackManager });
const embedModel = new OpenAIEmbedding();
mockEmbeddingModel(embedModel);
serviceContext = serviceContextFromDefaults({
callbackManager,
llm: languageModel,
embedModel,
llm: newLanguageModel,
embedModel: new OpenAIEmbedding(),
});
});
@@ -67,7 +76,7 @@ describe("CallbackManager: onLLMStream and onRetrieve", () => {
});
const queryEngine = vectorStoreIndex.asQueryEngine();
const query = "What is the author's name?";
const response = await queryEngine.query(query);
const response = await queryEngine.query(query, serviceContext);
expect(response.toString()).toBe("MOCK_TOKEN_1-MOCK_TOKEN_2");
expect(streamCallbackData).toEqual([
{
@@ -1,13 +1,15 @@
This is a [LlamaIndex](https://www.llamaindex.ai/) project using [FastAPI](https://fastapi.tiangolo.com/) bootstrapped with [`create-llama`](https://github.com/run-llama/LlamaIndexTS/tree/main/packages/create-llama).
This is a [LlamaIndex](https://www.llamaindex.ai/) project using [FastAPI](https://fastapi.tiangolo.com/) bootstrapped with [`create-llama`](https://github.com/run-llama/create-llama-ts).
## Getting Started
First, setup the environment:
First, setup the environment by running the following commands:
```
```bash
poetry install
poetry shell
```
```
By default, we use the OpenAI LLM (though you can customize, see app/api/routers/chat.py). As a result you need to specify an `OPENAI_API_KEY` in an .env file in this directory.
@@ -17,29 +19,33 @@ Example `backend/.env` file:
OPENAI_API_KEY=<openai_api_key>
```
Second, generate the embeddings of the documents in the `./data` directory (if this folder exists - otherwise, skip this step):
Second, generate the embeddings of the documents by following the steps below:
```
python app/engine/generate.py
```bash
python app/data/generate.py
```
```
Third, run the development server:
Next, run the development server with the command below:
```
python main.py
```
Then call the API endpoint `/api/chat` to see the result:
After running the server, call the API endpoint `/api/chat` to see the result using the following command:
```
curl --location 'localhost:8000/api/chat' \
```bash
curl --location '127.0.0.1:8000/api/chat' \
--header 'Content-Type: application/json' \
--data '{ "messages": [{ "role": "user", "content": "Hello" }] }'
```
```
You can start editing the API by modifying `app/api/routers/chat.py`. The endpoint auto-updates as you save the file.
Open [http://localhost:8000/docs](http://localhost:8000/docs) with your browser to see the Swagger UI of the API.
Now, open [http://localhost:8000/docs](http://localhost:8000/docs) with your browser to see the Swagger UI of the API.
The API allows CORS for all origins to simplify development. You can change this behavior by setting the `ENVIRONMENT` environment variable to `prod`:
@@ -47,10 +53,24 @@ The API allows CORS for all origins to simplify development. You can change this
ENVIRONMENT=prod uvicorn main:app
```
## Learn More
## Troubleshooting and Error Logs
### Troubleshooting Common GitHub Actions Issues
If the GitHub Actions run fails, please consider the following troubleshooting steps:
To learn more about LlamaIndex, take a look at the following resources:
- [LlamaIndex Documentation](https://docs.llamaindex.ai) - learn about LlamaIndex.
- [LlamaIndex Documentation](https://docs.llamaindex.ai) - learn more about LlamaIndex.
You can check out [the LlamaIndex GitHub repository](https://github.com/run-llama/llama_index) - your feedback and contributions are welcome!
### Accessing and Interpreting Error Logs
When the GitHub Actions run fails, you can access error logs to investigate the cause. Follow these steps to access the logs:
1. Navigate to the GitHub Actions page for the repository.
2. Click on the failed workflow to view the details.
3. Scroll down to find the error logs and examine the details.
The error logs provide valuable information to help identify the root cause of the failure.
You can check out [the LlamaIndex GitHub repository](https://github.com/run-llama/LlamaIndexTS) - your feedback and contributions are welcome!
@@ -1,7 +1,7 @@
from typing import List
from fastapi import APIRouter, Depends, HTTPException, status
from llama_index.chat_engine.types import BaseChatEngine
from app.engine.index import BaseChatEngine
from llama_index.llms.base import ChatMessage
from llama_index.llms.types import MessageRole
from pydantic import BaseModel
@@ -2,6 +2,8 @@ import os
from llama_index import ServiceContext
from llama_index.llms import OpenAI
from llama_index.engine import BaseChatEngine
from dotenv import load_dotenv
def create_base_context():
@@ -1,4 +1,4 @@
from llama_index.chat_engine import SimpleChatEngine
from app.engine.index import SimpleChatEngine
from app.context import create_base_context
@@ -1,4 +1,6 @@
from dotenv import load_dotenv
from fastapi import FastAPI, Request, status, HTTPException
from fastapi.middleware.cors import CORSMiddleware
load_dotenv()
@@ -11,7 +13,7 @@ from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
environment = os.getenv("ENVIRONMENT", "dev") # Default to 'development' if not set
environment = os.getenv("ENVIRONMENT", default="dev") # Default to 'development' if not set
if environment == "dev":
@@ -25,7 +27,7 @@ if environment == "dev":
allow_headers=["*"],
)
app.include_router(chat_router, prefix="/api/chat")
app.include_router(chat_router, prefix="/api/chat", tags=["chat"])
if __name__ == "__main__":
@@ -6,7 +6,7 @@ authors = ["Marcus Schiesser <mail@marcusschiesser.de>"]
readme = "README.md"
[tool.poetry.dependencies]
python = "^3.11,<3.12"
python = "^3.11"
fastapi = "^0.104.1"
uvicorn = { extras = ["standard"], version = "^0.23.2" }
llama-index = "^0.9.19"
@@ -1,4 +1,4 @@
This is a [LlamaIndex](https://www.llamaindex.ai/) project using [FastAPI](https://fastapi.tiangolo.com/) bootstrapped with [`create-llama`](https://github.com/run-llama/LlamaIndexTS/tree/main/packages/create-llama).
This is a [LlamaIndex](https://www.llamaindex.ai/) project using [FastAPI](https://fastapi.tiangolo.com/) bootstrapped with [`create-llama`](https://github.com/run-llama/create-llama-ts).
## Getting Started
@@ -26,7 +26,7 @@ python app/engine/generate.py
Third, run the development server:
```
python main.py
python app/main.py
```
Then call the API endpoint `/api/chat` to see the result:
@@ -53,4 +53,4 @@ To learn more about LlamaIndex, take a look at the following resources:
- [LlamaIndex Documentation](https://docs.llamaindex.ai) - learn about LlamaIndex.
You can check out [the LlamaIndex GitHub repository](https://github.com/run-llama/llama_index) - your feedback and contributions are welcome!
You can check out [the LlamaIndex GitHub repository](https://github.com/run-llama/LlamaIndexTS) - your feedback and contributions are welcome!