diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 1a88479cdd557f629132a7a401b61d01842d9d00..7e03e5c979cee22f5729afea84c51b9678cd2d7b 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -36,3 +36,6 @@ jobs:
         working-directory: ./packages/core
       - name: Run Type Check
         run: pnpm run type-check
+      - name: Run Circular Dependency Check
+        run: pnpm run circular-check
+        working-directory: ./packages/core
diff --git a/packages/core/jest.config.cjs b/packages/core/jest.config.cjs
index b359e058b5274f085faafdd9d5f7cb91c123ebdd..3f6d6b1470c105da06953348d096b8a6c7ed025c 100644
--- a/packages/core/jest.config.cjs
+++ b/packages/core/jest.config.cjs
@@ -2,5 +2,5 @@
 module.exports = {
   preset: "ts-jest",
   testEnvironment: "node",
-  testPathIgnorePatterns: ["/lib/"],
+  testPathIgnorePatterns: ["/lib/", "/node_modules/", "/dist/"],
 };
diff --git a/packages/core/package.json b/packages/core/package.json
index 8edcf06da56ef2161403517ed7a9f97ae6e4eef3..81523f32be4dfd59a314b3485155a3ff020976d6 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -81,6 +81,6 @@
     "modify-package-json": "node ./scripts/modify-package-json.mjs",
     "prepublish": "pnpm run modify-package-json && echo \"please cd ./dist and run pnpm publish\" && exit 1",
     "dev": "bunchee -w",
-    "circular-check": "madge --circular ./src/*.ts"
+    "circular-check": "madge -c ./src/index.ts"
   }
 }
diff --git a/packages/core/src/OutputParser.ts b/packages/core/src/OutputParser.ts
index 12d96ceff64a7d43185d48ca9e955ef5162af294..052eaf8c4aa62b970e2192b547d2aa84717500e7 100644
--- a/packages/core/src/OutputParser.ts
+++ b/packages/core/src/OutputParser.ts
@@ -1,20 +1,4 @@
-import { SubQuestion } from "./QuestionGenerator";
-
-/**
- * An OutputParser is used to extract structured data from the raw output of the LLM.
- */
-export interface BaseOutputParser<T> {
-  parse(output: string): T;
-  format(output: string): string;
-}
-
-/**
- * StructuredOutput is just a combo of the raw output and the parsed output.
- */
-export interface StructuredOutput<T> {
-  rawOutput: string;
-  parsedOutput: T;
-}
+import { BaseOutputParser, StructuredOutput, SubQuestion } from "./types";
 
 /**
  * Error class for output parsing. Due to the nature of LLMs, anytime we use LLM
diff --git a/packages/core/src/Prompt.ts b/packages/core/src/Prompt.ts
index b89fe772080f5a2878d7cbc9926b26e370f2e5a9..8e181fb9286dd033a0c732a61badfb1e18bc67db 100644
--- a/packages/core/src/Prompt.ts
+++ b/packages/core/src/Prompt.ts
@@ -1,6 +1,5 @@
 import { ChatMessage } from "./llm/types";
-import { SubQuestion } from "./QuestionGenerator";
-import { ToolMetadata } from "./Tool";
+import { SubQuestion, ToolMetadata } from "./types";
 
 /**
  * A SimplePrompt is a function that takes a dictionary of inputs and returns a string.
diff --git a/packages/core/src/QueryEngine.ts b/packages/core/src/QueryEngine.ts
index 790930d712025e8d5ffda32d8b0fb99b147ad088..8a3a2437eee25437f42237404a83713cb43758d6 100644
--- a/packages/core/src/QueryEngine.ts
+++ b/packages/core/src/QueryEngine.ts
@@ -1,13 +1,8 @@
 import { NodeWithScore, TextNode } from "./Node";
-import {
-  BaseQuestionGenerator,
-  LLMQuestionGenerator,
-  SubQuestion,
-} from "./QuestionGenerator";
+import { LLMQuestionGenerator } from "./QuestionGenerator";
 import { Response } from "./Response";
 import { BaseRetriever } from "./Retriever";
 import { ServiceContext, serviceContextFromDefaults } from "./ServiceContext";
-import { QueryEngineTool, ToolMetadata } from "./Tool";
 import { Event } from "./callbacks/CallbackManager";
 import { randomUUID } from "./env";
 import { BaseNodePostprocessor } from "./postprocessors";
@@ -16,34 +11,15 @@ import {
   CompactAndRefine,
   ResponseSynthesizer,
 } from "./synthesizers";
-
-/**
- * Parameters for sending a query.
- */
-export interface QueryEngineParamsBase {
-  query: string;
-  parentEvent?: Event;
-}
-
-export interface QueryEngineParamsStreaming extends QueryEngineParamsBase {
-  stream: true;
-}
-
-export interface QueryEngineParamsNonStreaming extends QueryEngineParamsBase {
-  stream?: false | null;
-}
-
-/**
- * A query engine is a question answerer that can use one or more steps.
- */
-export interface BaseQueryEngine {
-  /**
-   * Query the query engine and get a response.
-   * @param params
-   */
-  query(params: QueryEngineParamsStreaming): Promise<AsyncIterable<Response>>;
-  query(params: QueryEngineParamsNonStreaming): Promise<Response>;
-}
+import {
+  BaseQueryEngine,
+  BaseQuestionGenerator,
+  QueryEngineParamsNonStreaming,
+  QueryEngineParamsStreaming,
+  QueryEngineTool,
+  SubQuestion,
+  ToolMetadata,
+} from "./types";
 
 /**
  * A query engine that uses a retriever to query an index and then synthesizes the response.
diff --git a/packages/core/src/QuestionGenerator.ts b/packages/core/src/QuestionGenerator.ts
index eceac0303a7332d9e20a571428acd910d82136f4..b52ed5b04d7421de44d51adc8963e8c16a36a891 100644
--- a/packages/core/src/QuestionGenerator.ts
+++ b/packages/core/src/QuestionGenerator.ts
@@ -1,28 +1,18 @@
-import {
-  BaseOutputParser,
-  StructuredOutput,
-  SubQuestionOutputParser,
-} from "./OutputParser";
+import { SubQuestionOutputParser } from "./OutputParser";
 import {
   SubQuestionPrompt,
   buildToolsText,
   defaultSubQuestionPrompt,
 } from "./Prompt";
-import { ToolMetadata } from "./Tool";
 import { OpenAI } from "./llm/LLM";
 import { LLM } from "./llm/types";
-
-export interface SubQuestion {
-  subQuestion: string;
-  toolName: string;
-}
-
-/**
- * QuestionGenerators generate new questions for the LLM using tools and a user query.
- */
-export interface BaseQuestionGenerator {
-  generate(tools: ToolMetadata[], query: string): Promise<SubQuestion[]>;
-}
+import {
+  BaseOutputParser,
+  BaseQuestionGenerator,
+  StructuredOutput,
+  SubQuestion,
+  ToolMetadata,
+} from "./types";
 
 /**
  * LLMQuestionGenerator uses the LLM to generate new questions for the LLM using tools and a user query.
diff --git a/packages/core/src/Tool.ts b/packages/core/src/Tool.ts
deleted file mode 100644
index 9474f358c2b98e0085fafc86b290727cd9d0da32..0000000000000000000000000000000000000000
--- a/packages/core/src/Tool.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-import { BaseQueryEngine } from "./QueryEngine";
-
-export interface ToolMetadata {
-  description: string;
-  name: string;
-}
-
-/**
- * Simple Tool interface. Likely to change.
- */
-export interface BaseTool {
-  metadata: ToolMetadata;
-}
-
-/**
- * A Tool that uses a QueryEngine.
- */
-export interface QueryEngineTool extends BaseTool {
-  queryEngine: BaseQueryEngine;
-}
diff --git a/packages/core/src/embeddings/OpenAIEmbedding.ts b/packages/core/src/embeddings/OpenAIEmbedding.ts
index a777679f3fa7a4f9436c3e3beac3416255fb8c76..5fc46982575d5a70a491022ea29b288f092f7637 100644
--- a/packages/core/src/embeddings/OpenAIEmbedding.ts
+++ b/packages/core/src/embeddings/OpenAIEmbedding.ts
@@ -6,7 +6,7 @@ import {
   getAzureModel,
   shouldUseAzure,
 } from "../llm/azure";
-import { OpenAISession, getOpenAISession } from "../llm/openai";
+import { OpenAISession, getOpenAISession } from "../llm/open_ai";
 import { BaseEmbedding } from "./types";
 
 export const ALL_OPENAI_EMBEDDING_MODELS = {
diff --git a/packages/core/src/embeddings/types.ts b/packages/core/src/embeddings/types.ts
index b091c942c03c6e224f3a698ece3fc2dcd85f77ec..bff218875e5d829a13e36023fe970191f3969fb1 100644
--- a/packages/core/src/embeddings/types.ts
+++ b/packages/core/src/embeddings/types.ts
@@ -1,16 +1,6 @@
 import { BaseNode, MetadataMode } from "../Node";
 import { TransformComponent } from "../ingestion";
-import { similarity } from "./utils";
-
-/**
- * Similarity type
- * Default is cosine similarity. Dot product and negative Euclidean distance are also supported.
- */
-export enum SimilarityType {
-  DEFAULT = "cosine",
-  DOT_PRODUCT = "dot_product",
-  EUCLIDEAN = "euclidean",
-}
+import { SimilarityType, similarity } from "./utils";
 
 export abstract class BaseEmbedding implements TransformComponent {
   similarity(
diff --git a/packages/core/src/embeddings/utils.ts b/packages/core/src/embeddings/utils.ts
index 0c2ba7a28626fc2f8878aefda5c42fdb10ce753e..803701a7b5a58093b42e0d1cb6d9cdaa611dd5ef 100644
--- a/packages/core/src/embeddings/utils.ts
+++ b/packages/core/src/embeddings/utils.ts
@@ -2,8 +2,17 @@ import _ from "lodash";
 import { ImageType } from "../Node";
 import { DEFAULT_SIMILARITY_TOP_K } from "../constants";
 import { defaultFS } from "../env";
-import { VectorStoreQueryMode } from "../storage";
-import { SimilarityType } from "./types";
+import { VectorStoreQueryMode } from "../storage/vectorStore/types";
+
+/**
+ * Similarity type
+ * Default is cosine similarity. Dot product and negative Euclidean distance are also supported.
+ */
+export enum SimilarityType {
+  DEFAULT = "cosine",
+  DOT_PRODUCT = "dot_product",
+  EUCLIDEAN = "euclidean",
+}
 
 /**
  * The similarity between two embeddings.
diff --git a/packages/core/src/engines/chat/CondenseQuestionChatEngine.ts b/packages/core/src/engines/chat/CondenseQuestionChatEngine.ts
index 07ce7aad45b9b114f09ba7c975d011e5dbc89301..6d8e93b491c6ab692391539f4b12e32229b06fbc 100644
--- a/packages/core/src/engines/chat/CondenseQuestionChatEngine.ts
+++ b/packages/core/src/engines/chat/CondenseQuestionChatEngine.ts
@@ -4,7 +4,6 @@ import {
   defaultCondenseQuestionPrompt,
   messagesToHistoryStr,
 } from "../../Prompt";
-import { BaseQueryEngine } from "../../QueryEngine";
 import { Response } from "../../Response";
 import {
   ServiceContext,
@@ -12,6 +11,7 @@ import {
 } from "../../ServiceContext";
 import { ChatMessage, LLM } from "../../llm";
 import { extractText, streamReducer } from "../../llm/utils";
+import { BaseQueryEngine } from "../../types";
 import {
   ChatEngine,
   ChatEngineParamsNonStreaming,
diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts
index dd2e57fc5edf4e1d357b95514444b17d650d67b7..a668a4b9e50baf5bd9e57e98d4128ad605a1db86 100644
--- a/packages/core/src/index.ts
+++ b/packages/core/src/index.ts
@@ -10,7 +10,6 @@ export * from "./Response";
 export * from "./Retriever";
 export * from "./ServiceContext";
 export * from "./TextSplitter";
-export * from "./Tool";
 export * from "./callbacks/CallbackManager";
 export * from "./constants";
 export * from "./embeddings";
@@ -21,7 +20,7 @@ export * from "./ingestion";
 export * from "./llm";
 export * from "./nodeParsers";
 export * from "./postprocessors";
-export * from "./readers/AssemblyAI";
+export * from "./readers/AssemblyAIReader";
 export * from "./readers/CSVReader";
 export * from "./readers/DocxReader";
 export * from "./readers/HTMLReader";
@@ -33,3 +32,4 @@ export * from "./readers/SimpleMongoReader";
 export * from "./readers/base";
 export * from "./storage";
 export * from "./synthesizers";
+export type * from "./types";
diff --git a/packages/core/src/indices/BaseIndex.ts b/packages/core/src/indices/BaseIndex.ts
index 1f0ee6757dd325ac02ad35deca327e5e88f69017..c63b3891924930c1c2a3c4ab1bbe05ea71a20ffa 100644
--- a/packages/core/src/indices/BaseIndex.ts
+++ b/packages/core/src/indices/BaseIndex.ts
@@ -1,5 +1,4 @@
 import { BaseNode, Document, jsonToNode } from "../Node";
-import { BaseQueryEngine } from "../QueryEngine";
 import { BaseRetriever } from "../Retriever";
 import { ServiceContext } from "../ServiceContext";
 import { randomUUID } from "../env";
@@ -8,6 +7,7 @@ import { BaseDocumentStore } from "../storage/docStore/types";
 import { BaseIndexStore } from "../storage/indexStore/types";
 import { VectorStore } from "../storage/vectorStore/types";
 import { BaseSynthesizer } from "../synthesizers";
+import { BaseQueryEngine } from "../types";
 
 /**
  * The underlying structure of each index.
diff --git a/packages/core/src/indices/keyword/KeywordTableIndex.ts b/packages/core/src/indices/keyword/KeywordTableIndex.ts
index fe1ec7c8168aa58ea1960bafc3c4f6f274cbd6c4..8072aeb63673be9b6842d0d962dca4e9713d3046 100644
--- a/packages/core/src/indices/keyword/KeywordTableIndex.ts
+++ b/packages/core/src/indices/keyword/KeywordTableIndex.ts
@@ -1,6 +1,6 @@
 import { BaseNode, Document, MetadataMode } from "../../Node";
 import { defaultKeywordExtractPrompt } from "../../Prompt";
-import { BaseQueryEngine, RetrieverQueryEngine } from "../../QueryEngine";
+import { RetrieverQueryEngine } from "../../QueryEngine";
 import { BaseRetriever } from "../../Retriever";
 import {
   ServiceContext,
@@ -13,6 +13,7 @@ import {
   storageContextFromDefaults,
 } from "../../storage";
 import { BaseSynthesizer } from "../../synthesizers";
+import { BaseQueryEngine } from "../../types";
 import {
   BaseIndex,
   BaseIndexInit,
diff --git a/packages/core/src/indices/summary/SummaryIndex.ts b/packages/core/src/indices/summary/SummaryIndex.ts
index 391685dd895c494f362849a762fc50f77bd08216..774dfac2a4ec9bc6c5b52c8b6e83752df9cb3127 100644
--- a/packages/core/src/indices/summary/SummaryIndex.ts
+++ b/packages/core/src/indices/summary/SummaryIndex.ts
@@ -1,6 +1,6 @@
 import _ from "lodash";
 import { BaseNode, Document } from "../../Node";
-import { BaseQueryEngine, RetrieverQueryEngine } from "../../QueryEngine";
+import { RetrieverQueryEngine } from "../../QueryEngine";
 import { BaseRetriever } from "../../Retriever";
 import {
   ServiceContext,
@@ -18,6 +18,7 @@ import {
   CompactAndRefine,
   ResponseSynthesizer,
 } from "../../synthesizers";
+import { BaseQueryEngine } from "../../types";
 import {
   BaseIndex,
   BaseIndexInit,
diff --git a/packages/core/src/indices/vectorStore/VectorStoreIndex.ts b/packages/core/src/indices/vectorStore/VectorStoreIndex.ts
index 64c9a90e2cadef3df6d0879cc96aa35e09a5f7fa..832d46216b61a391effa00e1d00b8640448b0eb9 100644
--- a/packages/core/src/indices/vectorStore/VectorStoreIndex.ts
+++ b/packages/core/src/indices/vectorStore/VectorStoreIndex.ts
@@ -6,7 +6,7 @@ import {
   ObjectType,
   splitNodesByType,
 } from "../../Node";
-import { BaseQueryEngine, RetrieverQueryEngine } from "../../QueryEngine";
+import { RetrieverQueryEngine } from "../../QueryEngine";
 import { BaseRetriever } from "../../Retriever";
 import {
   ServiceContext,
@@ -26,6 +26,7 @@ import {
   storageContextFromDefaults,
 } from "../../storage";
 import { BaseSynthesizer } from "../../synthesizers";
+import { BaseQueryEngine } from "../../types";
 import {
   BaseIndex,
   BaseIndexInit,
diff --git a/packages/core/src/llm/LLM.ts b/packages/core/src/llm/LLM.ts
index aaaac65bf7b16c3545466b5c8dbd659724b69e6d..3df872512f4e497205feaf6009bbc67bcbb77a2f 100644
--- a/packages/core/src/llm/LLM.ts
+++ b/packages/core/src/llm/LLM.ts
@@ -25,9 +25,9 @@ import {
   shouldUseAzure,
 } from "./azure";
 import { BaseLLM } from "./base";
-import { OpenAISession, getOpenAISession } from "./openai";
+import { OpenAISession, getOpenAISession } from "./open_ai";
 import { PortkeySession, getPortkeySession } from "./portkey";
-import { ReplicateSession } from "./replicate";
+import { ReplicateSession } from "./replicate_ai";
 import {
   ChatMessage,
   ChatResponse,
diff --git a/packages/core/src/llm/index.ts b/packages/core/src/llm/index.ts
index a762899892dfa768af5646701d2616c0200a77ea..16dcd5353920905604864b2aae2b27ac1df88f06 100644
--- a/packages/core/src/llm/index.ts
+++ b/packages/core/src/llm/index.ts
@@ -1,5 +1,10 @@
 export * from "./LLM";
-export * from "./mistral";
+export {
+  ALL_AVAILABLE_MISTRAL_MODELS,
+  MistralAI,
+  MistralAISession,
+} from "./mistral";
 export { Ollama } from "./ollama";
+export * from "./open_ai";
 export { TogetherLLM } from "./together";
 export * from "./types";
diff --git a/packages/core/src/llm/openai.ts b/packages/core/src/llm/open_ai.ts
similarity index 100%
rename from packages/core/src/llm/openai.ts
rename to packages/core/src/llm/open_ai.ts
diff --git a/packages/core/src/llm/replicate.ts b/packages/core/src/llm/replicate_ai.ts
similarity index 97%
rename from packages/core/src/llm/replicate.ts
rename to packages/core/src/llm/replicate_ai.ts
index 6716b631f923609fbc6139ff213caca9d5be8da5..d452df38e63760b803ea94c39271467fb44bed9c 100644
--- a/packages/core/src/llm/replicate.ts
+++ b/packages/core/src/llm/replicate_ai.ts
@@ -28,5 +28,3 @@ export function getReplicateSession(replicateKey: string | null = null) {
 
   return defaultReplicateSession;
 }
-
-export * from "openai";
diff --git a/packages/core/src/readers/AssemblyAI.ts b/packages/core/src/readers/AssemblyAIReader.ts
similarity index 100%
rename from packages/core/src/readers/AssemblyAI.ts
rename to packages/core/src/readers/AssemblyAIReader.ts
diff --git a/packages/core/src/storage/vectorStore/SimpleVectorStore.ts b/packages/core/src/storage/vectorStore/SimpleVectorStore.ts
index 5c9170628440d1ea4e9d283dbec752f45a5e06b6..f4095e242e4e36abc2e4d5e49424dc93eafb0acc 100644
--- a/packages/core/src/storage/vectorStore/SimpleVectorStore.ts
+++ b/packages/core/src/storage/vectorStore/SimpleVectorStore.ts
@@ -4,7 +4,7 @@ import {
   getTopKEmbeddings,
   getTopKEmbeddingsLearner,
   getTopKMMREmbeddings,
-} from "../../embeddings";
+} from "../../embeddings/utils";
 import { defaultFS, path } from "../../env";
 import { GenericFileSystem, exists } from "../FileSystem";
 import { DEFAULT_PERSIST_DIR } from "../constants";
diff --git a/packages/core/src/tests/CallbackManager.test.ts b/packages/core/src/tests/CallbackManager.test.ts
index da56efd1c35f92a8d602a5d76e8a843a9ca39ce5..8c150a34324375def15d2693003b012758a07795 100644
--- a/packages/core/src/tests/CallbackManager.test.ts
+++ b/packages/core/src/tests/CallbackManager.test.ts
@@ -13,7 +13,7 @@ import { ResponseSynthesizer, SimpleResponseBuilder } from "../synthesizers";
 import { mockEmbeddingModel, mockLlmGeneration } from "./utility/mockOpenAI";
 
 // Mock the OpenAI getOpenAISession function during testing
-jest.mock("../llm/openai", () => {
+jest.mock("../llm/open_ai", () => {
   return {
     getOpenAISession: jest.fn().mockImplementation(() => null),
   };
diff --git a/packages/core/src/tests/MetadataExtractors.test.ts b/packages/core/src/tests/MetadataExtractors.test.ts
index 5d8ef8a35dd88fd0394362bfdd68df7a87eaf7c9..57026943edba5b56fcee30935cad9d4c9853e4f9 100644
--- a/packages/core/src/tests/MetadataExtractors.test.ts
+++ b/packages/core/src/tests/MetadataExtractors.test.ts
@@ -21,7 +21,7 @@ import {
 } from "./utility/mockOpenAI";
 
 // Mock the OpenAI getOpenAISession function during testing
-jest.mock("../llm/openai", () => {
+jest.mock("../llm/open_ai", () => {
   return {
     getOpenAISession: jest.fn().mockImplementation(() => null),
   };
diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4f38fdcaf342e9e4964686fe857e3e3503ebb953
--- /dev/null
+++ b/packages/core/src/types.ts
@@ -0,0 +1,82 @@
+/**
+ * Top level types to avoid circular dependencies
+ */
+
+import { Event } from "./callbacks/CallbackManager";
+import { Response } from "./Response";
+
+/**
+ * Parameters for sending a query.
+ */
+export interface QueryEngineParamsBase {
+  query: string;
+  parentEvent?: Event;
+}
+
+export interface QueryEngineParamsStreaming extends QueryEngineParamsBase {
+  stream: true;
+}
+
+export interface QueryEngineParamsNonStreaming extends QueryEngineParamsBase {
+  stream?: false | null;
+}
+
+/**
+ * A query engine is a question answerer that can use one or more steps.
+ */
+export interface BaseQueryEngine {
+  /**
+   * Query the query engine and get a response.
+   * @param params
+   */
+  query(params: QueryEngineParamsStreaming): Promise<AsyncIterable<Response>>;
+  query(params: QueryEngineParamsNonStreaming): Promise<Response>;
+}
+
+/**
+ * Simple Tool interface. Likely to change.
+ */
+export interface BaseTool {
+  metadata: ToolMetadata;
+}
+
+/**
+ * A Tool that uses a QueryEngine.
+ */
+export interface QueryEngineTool extends BaseTool {
+  queryEngine: BaseQueryEngine;
+}
+
+export interface SubQuestion {
+  subQuestion: string;
+  toolName: string;
+}
+
+/**
+ * An OutputParser is used to extract structured data from the raw output of the LLM.
+ */
+export interface BaseOutputParser<T> {
+  parse(output: string): T;
+
+  format(output: string): string;
+}
+
+/**
+ * StructuredOutput is just a combo of the raw output and the parsed output.
+ */
+export interface StructuredOutput<T> {
+  rawOutput: string;
+  parsedOutput: T;
+}
+
+export interface ToolMetadata {
+  description: string;
+  name: string;
+}
+
+/**
+ * QuestionGenerators generate new questions for the LLM using tools and a user query.
+ */
+export interface BaseQuestionGenerator {
+  generate(tools: ToolMetadata[], query: string): Promise<SubQuestion[]>;
+}