diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 75fbdb08b7..0fcf859fc0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -68,13 +68,9 @@ $ git remote -v > upstream https://github.com/Chainlit/chainlit.git (push) ``` -### Install JS dependencies +### Install dependencies -```sh -pnpm install -``` - -### Install python dependencies +The following command will install Python dependencies, Node (pnpm) dependencies and build the frontend. ```sh cd backend @@ -83,12 +79,6 @@ poetry install --with tests --with mypy --with dev ## Start the Chainlit server from source -You need to build the UI once before starting the server. - -```sh -pnpm run buildUi -``` - Start by running `backend/hello.py` as an example. ```sh @@ -116,16 +106,29 @@ If you visit `http://127.0.0.1:5174/`, it should connect to your local server. I ## Run the tests -Run `pnpm test` +### Backend unit tests -Once you create a pull request, the tests will automatically run. It is a good practice to run the tests locally before pushing. +This will run the backend's unit tests. -You will need to rebuild the UI if you updated it between test runs. +```sh +cd backend +pytest +``` + +### E2E tests + +This will run end to end tests, assessing both the frontend, the backend and their interaction: ```sh -pnpm run buildUi +pnpm test ``` +(Go grab a cup of something, this will take a while.) + +Once you create a pull request, the tests will automatically run. It is a good practice to run the tests locally before pushing. + +Make sure to run `poetry install` again whenever you've updated the frontend! + ### Run one test 1. Find the folder containing the e2e test that you're looking for in `cypress/e2e`. diff --git a/.github/workflows/e2e-tests.yaml b/.github/workflows/e2e-tests.yaml index 36f6ab6303..c7f704eb92 100644 --- a/.github/workflows/e2e-tests.yaml +++ b/.github/workflows/e2e-tests.yaml @@ -14,6 +14,12 @@ jobs: BACKEND_DIR: ./backend steps: - uses: actions/checkout@v3 + - uses: ./.github/actions/pnpm-node-install + name: Install Node, pnpm and dependencies. + with: + node-version: 22.7.0 + pnpm-version: 9.7.0 + pnpm-install-args: --no-frozen-lockfile - uses: ./.github/actions/poetry-python-install name: Install Python, poetry and Python dependencies with: @@ -21,14 +27,6 @@ jobs: poetry-version: 1.8.3 poetry-working-directory: ${{ env.BACKEND_DIR }} poetry-install-args: --with tests - - uses: ./.github/actions/pnpm-node-install - name: Install Node, pnpm and dependencies. - with: - node-version: 22.7.0 - pnpm-version: 9.7.0 - pnpm-install-args: --no-frozen-lockfile - - name: Build UI - run: pnpm run buildUi - name: Lint UI run: pnpm run lintUi - name: Run tests diff --git a/.github/workflows/mypy.yaml b/.github/workflows/mypy.yaml index 48ba387784..fff0c4bfe6 100644 --- a/.github/workflows/mypy.yaml +++ b/.github/workflows/mypy.yaml @@ -16,7 +16,7 @@ jobs: with: python-version: 3.9 poetry-version: 1.8.3 - poetry-install-args: --with tests --with mypy --with custom-data + poetry-install-args: --with tests --with mypy --with custom-data --no-root poetry-working-directory: ${{ env.BACKEND_DIR }} - name: Run Mypy run: poetry run mypy chainlit/ diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml index 71c72a07f7..70436c35a2 100644 --- a/.github/workflows/pytest.yaml +++ b/.github/workflows/pytest.yaml @@ -20,7 +20,7 @@ jobs: with: python-version: ${{ matrix.python-version }} poetry-version: 1.8.3 - poetry-install-args: --with tests --with mypy --with custom-data + poetry-install-args: --with tests --with mypy --with custom-data --no-root poetry-working-directory: ${{ env.BACKEND_DIR }} - name: Install fastapi ${{ matrix.fastapi-version }} run: poetry add fastapi@^${{ matrix.fastapi-version}} diff --git a/.gitignore b/.gitignore index b4003176a7..1b0f2b0171 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ dist-ssr .aider* .coverage + +backend/README.md diff --git a/README.md b/README.md deleted file mode 100644 index 14abf8790a..0000000000 --- a/README.md +++ /dev/null @@ -1,118 +0,0 @@ -# Welcome to Chainlit by Literal AI πŸ‘‹ - -[![](https://dcbadge.vercel.app/api/server/ZThrUxbAYw?style=flat)](https://discord.gg/k73SQ3FyUh) -[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/chainlit_io.svg?style=social&label=Follow%20%40chainlit_io)](https://twitter.com/chainlit_io) -![PyPI - Downloads](https://img.shields.io/pypi/dm/chainlit) -[![GitHub Contributors](https://img.shields.io/github/contributors/chainlit/chainlit)](https://github.com/chainlit/chainlit/graphs/contributors) -[![CI](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml/badge.svg)](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml) - -**Build production-ready Conversational AI applications in minutes, not weeks ⚑️** - -Chainlit is an open-source async Python framework which allows developers to build scalable Conversational AI or agentic applications. - -- βœ… ChatGPT-like application -- βœ… Embedded Chatbot & Software Copilot -- βœ… Slack & Discord -- βœ… Custom frontend (build your own agentic experience) -- βœ… API Endpoint - -Full documentation is available [here](https://docs.chainlit.io). You can ask Chainlit related questions to [Chainlit Help](https://help.chainlit.io/), an app built using Chainlit! - -> [!NOTE] -> Check out [Literal AI](https://literalai.com), our product to monitor and evaluate LLM applications! It works with any Python or TypeScript applications and [seamlessly](https://docs.chainlit.io/data-persistence/overview) with Chainlit by adding a `LITERAL_API_KEY` in your project. -> -> Chainlit is developed and maintained by the Literal AI team, which is currently focused on expanding the capabilities of Literal AI. While we continue to support and maintain Chainlit, we are also committed to enabling the community to contribute, particularly in areas like integrations and data layers. - -

- Chainlit user interface -

- -## Installation - -Open a terminal and run: - -```sh -pip install chainlit -chainlit hello -``` - -If this opens the `hello app` in your browser, you're all set! - -## πŸš€ Quickstart - -### 🐍 Pure Python - -Create a new file `demo.py` with the following code: - -```python -import chainlit as cl - - -@cl.step(type="tool") -async def tool(): - # Fake tool - await cl.sleep(2) - return "Response from the tool!" - - -@cl.on_message # this function will be called every time a user inputs a message in the UI -async def main(message: cl.Message): - """ - This function is called every time a user inputs a message in the UI. - It sends back an intermediate response from the tool, followed by the final answer. - - Args: - message: The user's message. - - Returns: - None. - """ - - - # Call the tool - tool_res = await tool() - - await cl.Message(content=tool_res).send() -``` - -Now run it! - -```sh -chainlit run demo.py -w -``` - -Quick Start - -## πŸŽ‰ Key Features and Integrations - -Full documentation is available [here](https://docs.chainlit.io). Key features: - -- [πŸ’¬ Multi Modal chats](https://docs.chainlit.io/advanced-features/multi-modal) -- [πŸ’­ Chain of Thought visualization](https://docs.chainlit.io/concepts/step) -- [πŸ’Ύ Data persistence + human feedback](https://docs.chainlit.io/data-persistence/overview) -- [πŸ› Debug Mode](https://docs.chainlit.io/data-persistence/enterprise#debug-mode) -- [πŸ‘€ Authentication](https://docs.chainlit.io/authentication/overview) - -Chainlit is compatible with all Python programs and libraries. That being said, it comes with integrations for: - -- [LangChain](https://docs.chainlit.io/integrations/langchain) -- [Llama Index](https://docs.chainlit.io/integrations/llama-index) -- [Autogen](https://github.com/Chainlit/cookbook/tree/main/pyautogen) -- [OpenAI Assistant](https://github.com/Chainlit/cookbook/tree/main/openai-assistant) -- [Haystack](https://docs.chainlit.io/integrations/haystack) - -## πŸ“š More Examples - Cookbook - -You can find various examples of Chainlit apps [here](https://github.com/Chainlit/cookbook) that leverage tools and services such as OpenAI, Anthropiс, LangChain, LlamaIndex, ChromaDB, Pinecone and more. - -Tell us what you would like to see added in Chainlit using the Github issues or on [Discord](https://discord.gg/k73SQ3FyUh). - -## πŸ’ Contributing - -As an open-source initiative in a rapidly evolving domain, we welcome contributions, be it through the addition of new features or the improvement of documentation. - -For detailed information on how to contribute, see [here](.github/CONTRIBUTING.md). - -## πŸ“ƒ License - -Chainlit is open-source and licensed under the [Apache 2.0](LICENSE) license. diff --git a/README.md b/README.md new file mode 120000 index 0000000000..c3e50587a5 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +backend/README.md \ No newline at end of file diff --git a/backend/README.md b/backend/README.md index e69de29bb2..ffd682b9af 100644 --- a/backend/README.md +++ b/backend/README.md @@ -0,0 +1,128 @@ +# Welcome to Chainlit by Literal AI πŸ‘‹ + +[![](https://dcbadge.vercel.app/api/server/ZThrUxbAYw?style=flat)](https://discord.gg/k73SQ3FyUh) +[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/chainlit_io.svg?style=social&label=Follow%20%40chainlit_io)](https://twitter.com/chainlit_io) +![PyPI - Downloads](https://img.shields.io/pypi/dm/chainlit) +[![GitHub Contributors](https://img.shields.io/github/contributors/chainlit/chainlit)](https://github.com/chainlit/chainlit/graphs/contributors) +[![CI](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml/badge.svg)](https://github.com/Chainlit/chainlit/actions/workflows/ci.yaml) + +**Build production-ready Conversational AI applications in minutes, not weeks ⚑️** + +Chainlit is an open-source async Python framework which allows developers to build scalable Conversational AI or agentic applications. + +- βœ… ChatGPT-like application +- βœ… Embedded Chatbot & Software Copilot +- βœ… Slack & Discord +- βœ… Custom frontend (build your own agentic experience) +- βœ… API Endpoint + +Full documentation is available [here](https://docs.chainlit.io). You can ask Chainlit related questions to [Chainlit Help](https://help.chainlit.io/), an app built using Chainlit! + +> [!NOTE] +> Check out [Literal AI](https://literalai.com), our product to monitor and evaluate LLM applications! It works with any Python or TypeScript applications and [seamlessly](https://docs.chainlit.io/data-persistence/overview) with Chainlit by adding a `LITERAL_API_KEY` in your project. +> +> Chainlit is developed and maintained by the Literal AI team, which is currently focused on expanding the capabilities of Literal AI. While we continue to support and maintain Chainlit, we are also committed to enabling the community to contribute, particularly in areas like integrations and data layers. + +

+ Chainlit user interface +

+ +## Installation + +Open a terminal and run: + +```sh +pip install chainlit +chainlit hello +``` + +If this opens the `hello app` in your browser, you're all set! + +### Development version + +The latest in-development version can be installed straight from GitHub with: + +```sh +pip install git+https://github.com/Chainlit/chainlit.git@dokterbob/build_frontend_on_poetry_build#subdirectory=backend/ +``` + +(Requires Node and pnpm installed on the system.) + +## πŸš€ Quickstart + +### 🐍 Pure Python + +Create a new file `demo.py` with the following code: + +```python +import chainlit as cl + + +@cl.step(type="tool") +async def tool(): + # Fake tool + await cl.sleep(2) + return "Response from the tool!" + + +@cl.on_message # this function will be called every time a user inputs a message in the UI +async def main(message: cl.Message): + """ + This function is called every time a user inputs a message in the UI. + It sends back an intermediate response from the tool, followed by the final answer. + + Args: + message: The user's message. + + Returns: + None. + """ + + + # Call the tool + tool_res = await tool() + + await cl.Message(content=tool_res).send() +``` + +Now run it! + +```sh +chainlit run demo.py -w +``` + +Quick Start + +## πŸŽ‰ Key Features and Integrations + +Full documentation is available [here](https://docs.chainlit.io). Key features: + +- [πŸ’¬ Multi Modal chats](https://docs.chainlit.io/advanced-features/multi-modal) +- [πŸ’­ Chain of Thought visualization](https://docs.chainlit.io/concepts/step) +- [πŸ’Ύ Data persistence + human feedback](https://docs.chainlit.io/data-persistence/overview) +- [πŸ› Debug Mode](https://docs.chainlit.io/data-persistence/enterprise#debug-mode) +- [πŸ‘€ Authentication](https://docs.chainlit.io/authentication/overview) + +Chainlit is compatible with all Python programs and libraries. That being said, it comes with integrations for: + +- [LangChain](https://docs.chainlit.io/integrations/langchain) +- [Llama Index](https://docs.chainlit.io/integrations/llama-index) +- [Autogen](https://github.com/Chainlit/cookbook/tree/main/pyautogen) +- [OpenAI Assistant](https://github.com/Chainlit/cookbook/tree/main/openai-assistant) +- [Haystack](https://docs.chainlit.io/integrations/haystack) + +## πŸ“š More Examples - Cookbook + +You can find various examples of Chainlit apps [here](https://github.com/Chainlit/cookbook) that leverage tools and services such as OpenAI, Anthropiс, LangChain, LlamaIndex, ChromaDB, Pinecone and more. + +Tell us what you would like to see added in Chainlit using the Github issues or on [Discord](https://discord.gg/k73SQ3FyUh). + +## πŸ’ Contributing + +As an open-source initiative in a rapidly evolving domain, we welcome contributions, be it through the addition of new features or the improvement of documentation. + +For detailed information on how to contribute, see [here](.github/CONTRIBUTING.md). + +## πŸ“ƒ License + +Chainlit is open-source and licensed under the [Apache 2.0](LICENSE) license. diff --git a/backend/build.py b/backend/build.py new file mode 100644 index 0000000000..2c8377632c --- /dev/null +++ b/backend/build.py @@ -0,0 +1,61 @@ +"""Build script gets called on poetry/pip build.""" + +import pathlib +import shutil +import subprocess + + +def pnpm_install(project_root, pnpm_path): + subprocess.run([pnpm_path, "install"], cwd=project_root, check=True) + + +def pnpm_buildui(project_root, pnpm_path): + subprocess.run([pnpm_path, "buildUi"], cwd=project_root, check=True) + + +def copy_frontend(project_root): + """Copy the frontend dist directory to the backend for inclusion in the package.""" + + # Create backend frontend dist dir + backend_frontend_dir = project_root / "backend" / "chainlit" / "frontend" / "dist" + backend_frontend_dir.mkdir(parents=True, exist_ok=True) + + # Recursively copy frontend_dist to backend_frontend_dir + frontend_dist = project_root / "frontend" / "dist" + + print(f"Copying {frontend_dist} to {backend_frontend_dir}") + shutil.copytree(frontend_dist, backend_frontend_dir, dirs_exist_ok=True) + + +def copy_copilot(project_root): + """Copy the copilot dist directory to the backend for inclusion in the package.""" + + # Create backend copilot dir + backend_copilot_dir = project_root / "backend" / "chainlit" / "copilot" / "dist" + backend_copilot_dir.mkdir(parents=True, exist_ok=True) + + # Recursively copy copilot_dist to backend_copilot_dir + copilot_dist = project_root / "libs" / "copilot" / "dist" + + print(f"Copying {copilot_dist} to {backend_copilot_dir}") + shutil.copytree(copilot_dist, backend_copilot_dir, dirs_exist_ok=True) + + +def build(): + # Find directory containing this file. + backend_dir = pathlib.Path(__file__).resolve().parent + project_root = backend_dir.parent + + pnpm = shutil.which("pnpm") + if not pnpm: + print("pnpm not found!") + exit(-1) + + pnpm_install(project_root, pnpm) + pnpm_buildui(project_root, pnpm) + copy_frontend(project_root) + copy_copilot(project_root) + + +if __name__ == "__main__": + build() diff --git a/backend/pyproject.toml b/backend/pyproject.toml index a4a844cedb..aa6511f3ef 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -28,13 +28,16 @@ classifiers = [ ] repository = "https://github.com/Chainlit/chainlit" readme = "README.md" -exclude = ["**/frontend/**/*", "**/copilot/**/**/"] -include = ["**/frontend/dist/**/*", "**/copilot/dist/**/*"] +exclude = ["chainlit/frontend/**/*", "chainlit/copilot/**/**/"] +include = ["chainlit/frontend/dist/**/*", "chainlit/copilot/dist/**/*"] [tool.poetry.scripts] # command_name = module_for_handler : function_for_handler chainlit = 'chainlit.cli:cli' +[tool.poetry.build] +script = "build.py" + [tool.poetry.dependencies] python = ">=3.9,<4.0.0" httpx = ">=0.23.0" diff --git a/frontend/package.json b/frontend/package.json index 93a7682195..635dbed1ce 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,7 @@ "scripts": { "preinstall": "npx only-allow pnpm", "dev": "vite", - "build": "tsc && vite build", + "build": "vite build", "preview": "vite preview", "lint": "eslint ./src --ext .ts,.tsx && tsc --noemit", "format": "prettier src/**/*.{ts,tsx} --write --loglevel error",