From e1a32dc472305f58d79fe8f8da4b42529267cbe7 Mon Sep 17 00:00:00 2001 From: yazawazi <47273265+Yazawazi@users.noreply.github.com> Date: Thu, 9 May 2024 08:49:02 +0800 Subject: [PATCH] doc: fix install and add cn --- README.md | 53 ++-- README.zh-CN.md | 655 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 565 insertions(+), 143 deletions(-) diff --git a/README.md b/README.md index 5fa295a8..45fb9bf4 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ https://github.com/TexteaInc/funix/assets/438579/86868ab5-ed6e-46e5-8dc5-9e3e4a3 -## What is Funix? +## What is Funix? * Funix automatically turns an ordinary Python function or class definition into a web app, which is accessible in a browser via a shareable link. * Funix is the frontend/backend/fullstack engineer and the infra/ops engineer for AI/Data/Science solo stars like you. @@ -25,6 +25,7 @@ https://github.com/TexteaInc/funix/assets/438579/86868ab5-ed6e-46e5-8dc5-9e3e4a3 * Funix is open-source and can be deployed on-premises. ## Use cases + * Startups: quickly build demos, iterate on MVPs, get user feedback and statistics, and pitch to investors or your mom. * Generative AI: instantly allow people to interact your GenAI model or idea. * STEM research: let people run your model and/or algorithm effortlessly. @@ -73,11 +74,9 @@ https://github.com/TexteaInc/funix/assets/438579/86868ab5-ed6e-46e5-8dc5-9e3e4a3 ## Getting started with Funix -**The Zen of Funix** is to generate widgets for function I/Os based on their types, instead of manually picking and customizing the widget for each I/O. **Funix to Python is like CSS to HTML or style class to LaTeX**. UI stuff is not intermingled with the core logic but defined separately. The type-to-widget mapping is controlled by a theme and new types can be defined on top of existing types. - - -The example below shows how common UI compoents are generated from four Python-native data types: `str`, `bool`, `Literal` and `range`, as well as types in popular packages such as `ipywidgets.Password`. The example below further maps default values to placeholders in the UI widgets. From this example, we can see that developers need to **learn nothing about Funix or do nothing to their existing code** before they can get an app. +**The Zen of Funix** is to generate widgets for function I/Os based on their types, instead of manually picking and customizing the widget for each I/O. **Funix to Python is like CSS to HTML or style class to LaTeX**. UI stuff is not intermingled with the core logic but defined separately. The type-to-widget mapping is controlled by a theme and new types can be defined on top of existing types. +The example below shows how common UI compoents are generated from four Python-native data types: `str`, `bool`, `Literal` and `range`, as well as types in popular packages such as `ipywidgets.Password`. The example below further maps default values to placeholders in the UI widgets. From this example, we can see that developers need to **learn nothing about Funix or do nothing to their existing code** before they can get an app. ```python import typing # Python native @@ -96,7 +95,7 @@ def input_widgets_basic( ![four input types](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/input_widgets.png) -The example below shows how `pandas.DataFrame` and `matplotlib.figure.Figure` that AI/data developers cannot be more familiar with are mapped to tables and charts in an app. +The example below shows how `pandas.DataFrame` and `matplotlib.figure.Figure` that AI/data developers cannot be more familiar with are mapped to tables and charts in an app. ```python import pandas, matplotlib.pyplot @@ -119,7 +118,7 @@ def table_and_plot( ![table and plot screenshot](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/table_plot.png) -You can even continuously update a plot based on user input. +You can even continuously update a plot based on user input. ```python import funix @@ -139,7 +138,6 @@ def sine(omega: funix.hint.FloatSlider(0, 4, 0.1)) -> matplotlib.figure.Figure: ![continuous sine function](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/continous_run_sine.gif) - ### Out-of-box support for classes and OOP Funix can turn each member method of a class into a page of an app. @@ -164,7 +162,6 @@ class A: ![class demo app gif](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/videos/class/class.gif) - A more advanced example of class is the wordle game. You can find the source code in [`examples/wordle.py`](./examples/games/wordle.py). In less than 100 lines, you can build Wordle! The screenshot is as follows: ![Wordle demo](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/wordle.png?raw=true) @@ -172,7 +169,7 @@ A more advanced example of class is the wordle game. You can find the source cod ### The quickest way to build GenAI apps You can wrap any Python function into a web app in Funix. -For example, you can take the ChatGPT demo code from OpenAI's APi reference and wrap it into a str-to-str function: +For example, you can take the ChatGPT demo code from OpenAI's APi reference and wrap it into a str-to-str function: ```python from openai import OpenAI @@ -186,21 +183,19 @@ def ChatGPT(prompt: str) -> str: {"role": "user", "content": prompt} ] ) -return completion.choices[0].message + return completion.choices[0].message ``` + which is turned into an app by Funix like below: ![screenshots/ChatGPT_lazy.png](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/chatGPT_lazy.png) +### Themes: the CSS for Python +**Funix to Python is like CSS to HTML or macros to LaTeX.** It separates the core logic and the UI. +All UI stuff is centrally defined in a JSON-based theme to avoid the repetitiveness of individually configuring widgets and keep a consistent look across apps. Consequently, a data scientist or a machine learning engineer does not need to think about anything UI. Just leave it to the UI team and Funix. - -### Themes: the CSS for Python - -**Funix to Python is like CSS to HTML or macros to LaTeX.** It separates the core logic and the UI. -All UI stuff is centrally defined in a JSON-based theme to avoid the repetitiveness of individually configuring widgets and keep a consistent look across apps. Consequently, a data scientist or a machine learning engineer does not need to think about anything UI. Just leave it to the UI team and Funix. - -Below is an example of a theme file. It defines the widget choices based on variable types and tweaks the `props` of UI components (currently only MUI ones are supported). Funix exposes frontend components and their `props` to developers, requiring them to know nothing about frontend. To know more about how to define and apply a theme, please refer to [the Themes section in the reference manual](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#themes). +Below is an example of a theme file. It defines the widget choices based on variable types and tweaks the `props` of UI components (currently only MUI ones are supported). Funix exposes frontend components and their `props` to developers, requiring them to know nothing about frontend. To know more about how to define and apply a theme, please refer to [the Themes section in the reference manual](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#themes). ```jsonc { @@ -222,7 +217,7 @@ Below is an example of a theme file. It defines the widget choices based on vari } ``` -To introduce a new data type, just declare a new Python class, and use a decorator to let Funix know. You can associate the type with a widget either on-the-fly (below) or via a theme file. +To introduce a new data type, just declare a new Python class, and use a decorator to let Funix know. You can associate the type with a widget either on-the-fly (below) or via a theme file. ```python from funix import funix, new_funix_type @@ -250,7 +245,7 @@ if __name__ == "__main__": ### Python-native to web-native -Funix repurposes some Python-native features to web features. +Funix repurposes some Python-native features to web features. First, Funix won't let your docstring or `print()` function calls go to waste. They will appear in the input and output panels of the web app. @@ -290,7 +285,7 @@ def stream() -> str: ![Streamt text to web](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/stream.gif?raw=true) -## Advanced features +## Advanced features ### History: Keep your call logs @@ -413,6 +408,7 @@ More examples in funix.hint.Image: ### Additional type support -1. If you want to use `git` related features (use project from GitHub), install funix by: +1. If you want to use `git` related features (use project from GitHub), install funix by: ```bash pip install funix[git] @@ -561,8 +558,8 @@ def gray_it(image: funix.hint.BytesImage) -> funix.hint.Image: In the last two cases above, you will need to compile the frontend by yourself. Suppose you are in the `funix` folder. Then run the following commands: 1. `cd frontend` -3. `yarn install` -4. `yarn start` +3. `yarn install` (you need install Node.JS and Yarn) +4. `yarn funix:build` #### Building the frontend with MUI Pro @@ -571,7 +568,7 @@ Our table widget uses advanced features in MUI Pro. If you have a MUI Pro licens 1. Install Node.js and Yarn; 2. Create a file called `.env` in the `frontend` folder; 3. Add `MUI_PRO_LICENSE_KEY=[your_key]` to the file; -4. Run `yarn funix:build` to build the frontend; +4. Run `yarn install && yarn funix:build` to build the frontend; 5. Done! ### Command line options @@ -609,8 +606,8 @@ Funix is open-sourced under the MIT License. Community contribution is not only ## Acknowledgment -Funix draws inspiration from FastAPI and Python-Fire: building software interfaces by inferring from function signatures containing type hints. We port this idea from the backend (FastAPI) or the terminal (Python-Fire) to the frontend. We also thank Streamlit, Gradio, PyWebIO, and Pynecone/Reflex. They inspired us. We are just too lazy to manually define widgets imperatively. Funix’s backend is implemented in Flask and the frontend in Material UI. +Funix draws inspiration from FastAPI and Python-Fire: building software interfaces by inferring from function signatures containing type hints. We port this idea from the backend (FastAPI) or the terminal (Python-Fire) to the frontend. We also thank Streamlit, Gradio, PyWebIO, and Pynecone/Reflex. They inspired us. We are just too lazy to manually define widgets imperatively. Funix’s backend is implemented in Flask and the frontend in Material UI. ## Contact -hello at funix dot io \ No newline at end of file +hello at funix dot io diff --git a/README.zh-CN.md b/README.zh-CN.md index 6fa1a09a..fd0c5998 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,199 +1,624 @@ -# Funix —— 无需手动创建部件,即可构建 Web 程序 +

+ + Funix.io
+ + 在 Python 中以最快捷的方式构建 Web 程序 +

-Funix 可自动将一个普通的 Python 函数转换为一个可用的 Web 程序,而无需你手动创建部件(见下文示例)。仅仅只需在你的函数上添加 `@funix` 装饰器,它就会成为 Web 应用供任何人使用,他们无需任何编程知识。 - -Funix 还支持复杂的数据类型和部件,如多列数据表或者 Matplotlib 图表。如果你想要自定义 UI,没关系,Funix 支持声明式语法,可以在装饰器中完成对组件的自定义。Funix 是同时也是非侵入式的,你仍然可以像往常一样在本地运行或调试你的 Python 代码。
[![PyPI version](https://badge.fury.io/py/funix.svg)](https://badge.fury.io/py/funix) +[![](https://dcbadge.vercel.app/api/server/JyANAMUAHM?style=flat)](https://discord.gg/JyANAMUAHM) -

快速入门指南和例子展示(英语)

+

导览视频 | 快速上手 | 演示内容 | 开发手册

-[English](README.md) +https://github.com/TexteaInc/funix/assets/438579/86868ab5-ed6e-46e5-8dc5-9e3e4a3cdc3f -https://user-images.githubusercontent.com/438579/219586150-7ff491dd-dfea-41ea-bfad-4610abf1fe20.mp4 +
-在 YouTube 上播放 +## Funix 是什么? -

+* Funix 可将普通的 Python 函数或类转换为网络应用程序,并且可通过链接共享,在浏览器中访问。 +* Funix 流动不居,可成为前端/后端亦或全栈工程师,也可成为架构/运维工程师,辅佐您这样的人工智能/数据/科学领域的独行侠。 +* Funix 为那些编写最核心、最具创新性代码之人,提供无代码或低代码的解决方案。 +* Funix 是开源软件,可在企业内部部署。 - +## 使用场景 + +* 初创企业:快速构建演示产品,迭代原型,获取用户反馈并统计数据,向投资者或您的母亲推荐。 +* 创成式 AI:让人们与你的 GenAI 模型或想法即时活动。 +* STEM 研究:让人们不费吹灰之力就能运行您的模型或算法。 +* 数据浏览器:Funix 可成为浏览数据、图表的工具。 +* A/B 测试和数据标注:可用于收集人工标注的信息和偏好。 + +## 主要优势 + +* **极简主义、开箱即用**:仅需对现有代码进行少量修改,亦或不进行修改就可使用。 +* **Python 中的 CSS**:部件(Widgets)基于变量类型和样式主题自动生成,而非手动单独设置,从而实现了跨 Funix 应用程序的集中、可重用和一致的用户界面。 +* **非侵入性和声明式**:用户界面配置作为 JSON 字符串,与核心逻辑分开。您的代码可照旧运行、导入和调用。 +* **天生 Pythonic 者**:将 Python 原生关键字对应到 Web 应用程序的功能:`global` 用于会话,`yield` 用于流式传输,以及用于随时展示到前端的 `print`。 +* **应用,而非 Demo**:开箱即支持[访问控制](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#secret),调用追踪和不追踪支持,[多页面程序](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#multipage-apps-and-sessionsstates) 和应用间数据传输,会话管理,动态输入,后端遥测等等…… + +### 喜欢 Funix,点个 Star 吧 + +![Borrowed from AppFlowy](https://github.com/AppFlowy-IO/AppFlowy/raw/main/doc/imgs/howtostar.gif) + +## 你好,世界 + +1. 安装 Funix ([高级安装方式]](#安装)): + + ```sh + pip install funix + ``` +2. 将下列代码保存为 `hello.py`:- -> **WIP**: Funix 仍在开发中, 如果你有任何问题,不必拘束,请[开启一个 issue](https://github.com/TexteaInc/funix/issues/new)。 + ```python + def hello(your_name: str) -> str: + return f"Hello, {your_name}." + ``` -## 快速浏览 +3. 运行如下代码: -在你的函数上面只需添加两行代码,该函数就会被转换为一个 Web 程序: + ```bash + funix hello.py + ``` + +4. Funix 将会唤起您的浏览器,访问 `http://localhost:3000`: + + ![screenshots/hello.png](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/hello.png) + + + +## 快速上手 + +**Funix 之道**便是根据函数的入参类型和返回类型生成部件,而非为每个参数挑选和定制部件。**Funix 之于 Python,就如 CSS 之于 HTML,宏之于 LaTeX**。UI 相关的内容不与核心逻辑混合,而是单独定义。类型-部件的映射由主题控制,还可在现有的类型基础上定义新的类型。 + +下方的示例展示了如何从四种 Python 原生类型生成普通的 UI 组件:`str`, `bool`, `Literal` 和 `range`,以及流行软件包中的类型,如 `ipywidgets.Password`。下面的示例还进一步将默认值映射到用户界面部件中的占位符。从此中,我们可以看到开发人员**无需学习任何有关 Funix 的知识,也无需对现有代码做任何修改**就可获取一个应用程序。 ```python -from funix import funix # 添加第一行 +import typing # Python native + +import ipywidgets # popular UI library + +def input_widgets_basic( + prompt: str = "Who is Oppenheimer?", + advanced_features: bool = True, + model: typing.Literal['GPT-3.5', 'GPT-4.0', 'Falcon-7B'] = 'GPT-4.0', + max_token: range(100, 200, 20) = 140, + openai_key: ipywidgets.Password = "1234556", + ) -> str: + pass +``` -@funix() # 添加第二行 -def hello(your_name: str) -> str: - return f"Hello, {your_name}." +![four input types](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/input_widgets.png) + +下方的示例展示了人工智能/数据开发人员再熟悉不过的 `pandas.DataFrame` 和 `matplotlib.figure.Figure` 是如何映射到应用程序中的表格和图表的。 + +```python +import pandas, matplotlib.pyplot +from numpy import arange, log +from numpy.random import random + +def table_and_plot( + df: pandas.DataFrame = pandas.DataFrame({ + "a": arange(500) + random(500)/5, + "b": random(500)-0.5 + log(arange(500)+1), + "c": log(arange(500)+1) }) + ) -> matplotlib.figure.Figure: + + fig = matplotlib.pyplot.figure() + matplotlib.pyplot.plot(df["a"], df["b"], 'b') + matplotlib.pyplot.plot(df["a"], df["c"], 'r') + + return fig ``` -将上述代码保存为 `hello.py`,随后在终端中执行: +![table and plot screenshot](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/table_plot.png) -```bash -funix hello +你甚至可以根据用户随时的输入不断更新图像: + +```python +import funix +import matplotlib.pyplot, matplotlib.figure +import numpy + +@funix.funix( + autorun=True, +) +def sine(omega: funix.hint.FloatSlider(0, 4, 0.1)) -> matplotlib.figure.Figure: + fig = matplotlib.pyplot.figure() + x = numpy.linspace(0, 20, 200) + y = numpy.sin(x*omega) + matplotlib.pyplot.plot(x, y, linewidth=5) + return fig ``` -这个 Web 程序将会在 `http://localhost:3000` 中启动,并自动在浏览器窗口打开。 +![continuous sine function](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/continous_run_sine.gif) -![screenshots/hello.png](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/hello.png) +### 开箱即支持类与 OOP -## 案例展览 +Funix 可将类中的每一个方法变成应用程序中的一个页面。 -### 在 Python 中最短的 Dall-E Web 程序 +只需两行代码,下方的示例就能将类定义转化为多页面应用程序,其中类对象的实例化在与类的构造函数相对应的页面中完成,对象的成员值可在其他页面中查看和更新。**无需手动公开**类的成员方法。 ```python -from funix import funix # 添加第一行 -from funix.hint import Images # 添加第二行 -import openai # pip install openai +from funix import funix_class -openai.api_key = os.environ.get("OPENAI_KEY") +@funix_class() +class A: + def __init__(self, a: int): + self.a = a + return f"`self.a` has been initialized to {self.a}" -@funix() # 添加第三行 -def dalle(prompt: str = "a cat") -> Image: - response = openai.Image.create(prompt=prompt, n=1, size="1024x1024") - return response["data"][0]["url"] + def update_a(self, b: int) -> str: + self.a = b + return f"`self.a` has been updated to {self.a}" + + def print_a(self) -> str: + return f"The value of `self.a` is {self.a}" ``` -![Dalle demo](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/dalle.jpg) +![class demo app gif](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/videos/class/class.gif) + +Wordle 游戏就是一个更高级的例子,你可以从这里获取它的源代码:[`examples/wordle.py`](./examples/games/wordle.py)。不到百行就可实现 Wordle,来看截图: + +![Wordle demo](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/wordle.png?raw=true) + +### 搭建 GenAI 应用程序的最快方式 -### 复合式 UI +在 Funix 中,你可将任何 Python 函数都变为 Web 应用。例如,您可以从 OpenAI 的 API 参考资料中获取 ChatGPT 演示代码,并将其封装为 str-to-str 函数: ```python -from typing import List -import matplotlib.pyplot as plt -from matplotlib.figure import Figure +from openai import OpenAI + +def ChatGPT(prompt: str) -> str: + client = OpenAI() + + completion = client.chat.completions.create( + model="gpt-3.5-turbo", + messages=[ + {"role": "user", "content": prompt} + ] + ) + return completion.choices[0].message +``` -@funix( - widgets={ - "a": "sheet", - "b": ["sheet", "slider[0,1,0.01]"] +这样,大功告成,如下所示: + +![screenshots/ChatGPT_lazy.png](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/chatGPT_lazy.png) + +### 主题:Python 中的 CSS + +**Funix 之于 Python,就如 CSS 之于 HTML,宏之于 LaTeX** 主题分隔了主要的逻辑和 UI 内容。 +所有 UI 内容都集中在一个 JSON 格式的主题中被定义,以避免重复单独配置部件,并在不同应用程序中保持一致的外观。因此,数据科学家或机器学习工程师无需考虑任何用户界面问题,只需将其交给 UI 团队和 Funix 即可。 + +下方是一个主题文件的示例。它根据变量类型定义部件如何选择,并调整用户界面的组件(目前仅支持 MUI)。Funix 向开发人员公开了前端组件及其属性(`props`),无需他们了解有关前端的知识。如果想知道如何定义和应用一个主题,请移步至[开发手册中的主题章节](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#themes)。 + +```jsonc +{ + "name": "test_theme", + "widgets": { // dict, map types to widgets + "str": "inputbox", // using Funix' widget shorthand + "int": "slider[0,100,2]", // using Funix' widget shorthand + "float": { + "widget": "@mui/material/Slider", // using MUI's widget + // https://mui.com/material-ui/api/slider + "props": { + "min": 0, + "max": 100, + "step": 0.1 } + }, + "Literal": "radio" + }, +} +``` + +要想引入新数据类型并在 Funix 中使用,您只需要声明一个新的 Python 类,并使用装饰器让 Funix 知道。你可以通过在代码中随时插入的定义(如下)或主题文件将该类型与 widget 关联: + +```python +from funix import funix, new_funix_type + +@new_funix_type( + widget = { + "widget": "@mui/material/TextField", + "props": { + "type": "password", + "placeholder": "Enter a secret here." + } + } ) +class blackout(str): + def print(self): + return self + " is the message." -# 下面是一个简单的 matplotlib 函数 -def table_plot(a: List[int], b: List[float]) -> Figure: - fig = plt.figure() - plt.plot(a, b) - return fig +@funix() +def hoho(x: blackout = "Funix Rocks!") -> str: + return x.print() + +if __name__ == "__main__": + print (hoho(blackout('Fun'))) ``` -![table plot demo static](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/table_plot.png) +### 原生 Python 功能到 Web + +Funix 可将一些 Python 原生功能转译为 Web 功能。 + +首先,Funix 并不会将您的 docstring 或 `print()` 函数调用白白浪费。它们会出现在 Web 应用程序的输入、输出面板上。 +```python +from funix import funix +@funix( + print_to_web=True +) +def foo() -> None: + """ + ## What a great app in Funix! + + Funix won't let your docstring go to waste. + """ + print("It supports **Markdown**.") + print ("And HTML.") + return None +``` -### 声明式的 UI 配置 +![Docstring and print to web](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/docstring_and_print.png?raw=true) -在 Funix 中,你的 UI 配置可以单独写到额外的配置文件或主题中,这么做可以使你只需要关注功能而非 UI。 +将文本流式传输到网页上,只需要简单地使用 `yield`: ```python -from funix import funix_yaml +import time -@funix_yaml(""" - widgets: - x: slider[0,10,1] - op: radio - whitelist: - op: - - square - - cube -""") +def stream() -> str: + """ + This function is used to test the stream feature of Funix. + """ + message = "We the People of the United States, in Order to form a more perfect Union, establish Justice, insure domestic Tranquility, provide for the common defence, promote the general Welfare, and secure the Blessings of Liberty to ourselves and our Posterity, do ordain and establish this Constitution for the United States of America." -def power(x: int, op: str) -> Markdown: - if op =="square": - return f"\ -* The _square_ of {x} is **{x * x}**. \n \ -* Made by [Funix](http://funix.io)" - elif op == "cube": - # return x * x * x - return f"\ -* The _cube_ of {x} is **{x * x * x}**. \n \ -* Made by [Funix](http://funix.io)" + for i in range(len(message)): + time.sleep(0.01) + yield message[0:i] ``` -![power slider radio](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/power_slider_radio.png) +![Streamt text to web](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/stream.gif?raw=true) -## 安装 +## 高级功能 -### 从 PyPI 安装 +### 历史记录:保存您的调用历史 -```bash -pip install funix +
+ +点击展开/收起 + + +我们从许多用户那里听到的一个功能要求是,他们不会把 Funix 转换的 App 作为仅使用几次的 Demo 程序来使用,而是将其作为一个真正的应用程序来反复使用。在这种情况下,他们希望保留应用程序的调用记录。Funix 默认支持此功能。您可以点击应用程序右上角的历史记录按钮访问应用程序的历史记录。 + +![history sidebar](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/history_sidebar.gif) + +
+ +### 多页面数据传递和会话或状态管理 + +
+ +点击展开/收起 + + +一个真正的应用程序通常有多个页面,例如,在一个页面设置 OpenAI 的令牌密钥,然后在其他 GenAI 页面使用该令牌。同一个 `.py` 脚本中的函数将成为一个 App 的不同页面。任何全局变量都可用于在函数间传递数据。在使用 `-t` 标志启动 Funix 时,他会进一步将全局变量会话化,这样不同的用户就可以拥有自己的会话。下面是一个简单的例子和相应的 GIF 动画。在 GIF 动画中,您可以看到两个浏览器会话中的 `y` 变量有所不同。 + +```python +import funix + +y = "The default value of y." + +@funix.funix() +def set_y(x: str="123") -> str: + global y + y = x + return "Y has been changed. Now check it in the get_y() page." + + +@funix.funix() +def get_y() -> str: + return y +``` + +![session](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/session.gif) + +
+ +### 预填充 + +
+ +点击展开/收起 + + +函数间传递数据的一种特殊情况便是,使用一个函数的返回值作为另一个函数参数的初始值。这种情况称之为预填充。Funix 通过装饰器属性 `pre_fill` 来支持预填充。下方是一个示例: + +```python +import funix + +def first_action(x: int) -> int: + return x - 1 + +def second_action(message: str) -> list[str]: + return message.split(" ") + +def third_action(x: int, y: int) -> dict: + return {"x": x, "y": y} + +@funix.funix( + pre_fill={ + "a": first_action, + "b": (second_action, -1), + "c": (third_action, "x") + } +) +def final_action(a: int, b: str, c: int) -> str: + return f"{a} {b} {c}" ``` -### 从 GitHub 安装 + +
+ +### 密钥:访问控制 -你可以直接透过以下命令直接安装: +
+ +点击展开/收起 + + +> [!NOTE] +> 这不是保护您应用程序的最佳实践。 + +为了保护您的代码(例如,与 OpenAI 相关的函数,可能会导致一些经济损失),您可以使用 `secret` 选项: ```bash -pip install "git+https://github.com/TexteaInc/funix.git" +funix my_app.py --secret my_secret_token # 您自己提供 Token +# or +funix my_app.py --secret True # 随机生成 Token ``` -### 本地安装 +令牌将展示在终端上,示例如下: -如果你想手动从本地安装: +```bash +$ funix hello.py --secret True +Secrets: +--------------- +Name: hello +Secret: 8c9f55d0eb74adbb3c87a445ea0ae92f +Link: http://127.0.0.1:3000/hello?secret=8c9f55d0eb74adbb3c87a445ea0ae92f +``` -1. `git clone https://github.com/TexteaInc/funix` -2. `cd funix` -3. `pip install -e .` (如果 pip 坚持要安装到全局环境中,请带上 `--prefix=~/.local` 参数。 参见 [#24](https://github.com/TexteaInc/funix/issues/24) 和 [#23](https://github.com/TexteaInc/funix/issues/23)) +需要在 URL 中包含令牌或手动输入令牌才能执行应用程序。 +![secret](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/secret.gif) -## 使用 +
+ +## 演示内容 + +更多例子可在开发手册或在 ./examples 文件夹中可见。 + +* [ChatPaper](https://github.com/forrestbao/ChatPaper)(它好比流行的 ChatPDF。但在 Funix 中,只需要 70 行代码。) +* [mFlux](https://github.com/Yazawazi/MFlux)(合成生物学) + +### ChatGPT,多轮对话 + +
+ examples/AI/chatGPT_multi_turn.py 👈 点我查看/收起源码 + + ```python + import os + import IPython + import openai + openai.api_key = os.environ.get("OPENAI_KEY") + + messages = [] # list of dicts, dict keys: role, content, system + + def print_messages_html(messages): + printout = "" + for message in messages: + if message["role"] == "user": + align, left, name = "left", "0%", "You" + elif message["role"] == "assistant": + align, left, name = "right", "30%", "ChatGPT" + printout += f'
{name}: {message["content"]}
' + return printout + + import funix + @funix.funix( + direction="column-reverse", + ) + def ChatGPT_multi_turn(current_message: str) -> IPython.display.HTML: + current_message = current_message.strip() + messages.append({"role": "user", "content": current_message}) + completion = openai.ChatCompletion.create( + messages=messages, + model='gpt-3.5-turbo', + max_tokens=100, + ) + chatgpt_response = completion["choices"][0]["message"]["content"] + messages.append({"role": "assistant", "content": chatgpt_response}) + + # return print_messages_markdown(messages) + return print_messages_html(messages) -```text -usage: funix [-h] [-H 127.0.0.1] [-p 3000] [-F] [-B] [main_class] + ``` -Funix: Building web apps without manually creating widgets +
-positional arguments: - main_class Main class to import +![Multiturn chat](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/chatGPT_multiturn.png) -options: - -h, --help show this help message and exit - -H 127.0.0.1, --host 127.0.0.1 - Host of frontend and backend - -p 3000, --port 3000 Port of frontend and backend - -F, --no-frontend Disable frontend server - -B, --no-browser Disable auto open browser +### 用 Python 编写最短的 Dall-E Web App + +```python +from funix import funix # add line one +from funix.hint import Images # add line two +import openai # pip install openai + +openai.api_key = os.environ.get("OPENAI_KEY") + +@funix() # add line three +def dalle(prompt: str = "a cat") -> Image: + response = openai.Image.create(prompt=prompt) + return response["data"][0]["url"] ``` -通常你可以使用 `python -m funix [module]` 直接启动,在 `examples` 文件夹里有一些简单的例子带你了解 Funix,你可以通过以下命令打开示例: +![Dalle demo](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/dalle.jpg) + + + +### 生物信息学:矢量修剪 + +[examples/bioinformatics/vector_strip.py](./examples/bioinformatics/vector_strip.py) 👈 点击查看源码 + +![bioinfo vector strip](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/bioinfo_vector_strip.png) + +### 多媒体输入输出 + +
+examples/multimedia/rgb2gray.py 👈 点我查看/收起源码 + +```python +import io # Python's native + +import PIL # the Python Image Library +import funix + +@funix.funix( + title="Convert color images to grayscale images", +) +def gray_it(image: funix.hint.BytesImage) -> funix.hint.Image: + img = PIL.Image.open(io.BytesIO(image)) + gray = PIL.ImageOps.grayscale(img) + output = io.BytesIO() + gray.save(output, format="PNG") + return output.getvalue() +``` + +
+ +![shipping example](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/rgb2gray.png) + +### 布局和 EasyPost 快递单 + +[`examples/layout_easypost_shipping.py`](./examples/layout_easypost_shipping.py) 👈 点击查看源码 + +![shipping example](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/easypost_shipping.png) + +## 使用 + +### 安装 + +* 从 PyPI 安装(稳定版本,缺少最新功能) + + ```bash + pip install funix + ``` + +* 从 GitHub 安装(开发或稳定版本) + + ```bash + pip install "git+https://github.com/TexteaInc/funix.git@develop" # 开发 + pip install "git+https://github.com/TexteaInc/funix.git" # 稳定 + ``` + +* 本地开发 + + ```bash + git clone -b develop https://github.com/TexteaInc/funix + cd funix + pip install -e . + ``` + + 添加 `--prefix=~/.local` 如果 pip 试图将其安装在系统路径。详见 [#24](https://github.com/TexteaInc/funix/issues/24) 和 [#23](https://github.com/TexteaInc/funix/issues/23) + +### 额外支持 + +1. 如果你想使用 Git 相关的功能,比如从 GitHub 拉取项目,请这样安装 Funix: + + ```bash + pip install funix[git] + ``` + +2. 如果你想使用 `ipython` 相关的功能: + + ```bash + pip install funix[ipython] + `` + +3. 或许未来有其他可选的新功能,您可以试着安装完全的 Funix: + + ```bash + pip install funix[all] + ``` + +### 构建前端 + +如果您需要参与 Funix 的工作,或使用开发版本的 Funix,您需要自己构建前端。假设您已在 `funix` 文件夹中,请运行以下命令: + +1. `cd frontend` +2. `yarn install`(你需要安装 Node.JS 和 Yarn 包管理器) +3. `yarn funix:build`(构建前端以便于 Funix 使用) + +对于需要调试的开发者,以下是简单的指南: + +1. `yarn funix:test`(进入开发模式) +2. `funix xxx -p 8080 -F`(使用 8080 端口的无前端模式) + +这样,您应该可以调试Funix 的前后端与您的应用程序了。 + +#### 使用 MUI Pro + +我们的表格组件可以使用 MUI Pro 中的高级功能。如果你有一个 MUI Pro 的证书许可,你可以使用自己的 MUI Pro 证书并构建前端: + +1. 确保安装了 Node.js 和 Yarn; +2. 在 `frontend` 文件夹中创建 `.env` 文件; +3. 添加 `MUI_PRO_LICENSE_KEY=[your_key]` 到你的文件; +4. 运行 `yarn install && yarn funix:build` 构建前端; +5. 万事大吉! + +### 命令行选项 + +运行下面的命令查看命令行选项: ```bash -cd examples -python -m funix examples -python -m funix examples_better # Examples V2 😄 +funix -h ``` -安装位于 GitHub 的最新代码,你可以直接通过 `funix [module]` 命令启动。 +### 在 Python 中调用 Funix + +除了从命令行启动 Funix 外,您还可在 `.py` 脚本中使用 Funix: + +```python +import funix + +@funix.funix() +def hello(your_name: str) -> str: + return f"Hello, {your_name}." -## 构建前端 +if __name__ == "__main__": + funix.run(__file__) +``` -在 Funix 中,我们已经打包好了前端,你可以直接使用,同时也有一个部署在[公网的前端页面](https://funix.vercel.app/)。如果你想自行构建前端,你可以通过以下命令: +### 公开 Funix 应用程序 ```bash -# 请先 clone 本项目并进入项目文件夹 -cd frontend -yarn install # 安装依赖 -yarn build # 构建 -yarn funix:build # 构建到 Funix Python 中 -yarn funix:test # 启动 Funix 前端开发环境(这会自动设置后端为 http://127.0.0.1:8080) +funix [module] --host [your_server_ip] ``` -## 如何参与贡献 +## 如何贡献 + +Funix 采用 MIT 许可开源。我们不仅欢迎社区贡献,而且希望来自社区的贡献。如果您准备好了,请随时 Fork 并提出拉取请求。您还可以通过 [Issue 追踪器](https://github.com/TexteaInc/funix/issues/new)或我们的 [Discord 服务器](https://discord.gg/JyANAMUAHM)报告错误,建议新功能等。 -Funix 是在 MIT 许可证下开源的。我们不但欢迎而且希望社区做出贡献。当你准备好的时候,请随意 fork 本项目并 PR。你也可以通过 [Issue Tracker](https://github.com/TexteaInc/funix/issues/new) 报告错误,建议新功能等。 +## 致谢 -## 团队 +Funix 从 FastAPI 和 Google Fire 中汲取灵感:透过推断包含类型提示的函数签名来构建软件界面。我们从这一想法从后端(FastAPI)或终端(Python-Fire)移植到前端。我们还要感谢 Streamlit、Gradio、PyWebIO 和 Pynecone/Reflex。它们启发了我们。我们只是太懒了,懒得手动定义部件。Funix 的后端由 Flask 实现,前端由 MUI 实现。 -Textea 的 Funix 团队由以下人员组成: +## 联系方式 -* [Ruixuan Tu](https://github.com/Turx) -* [Yazawazi](https://github.com/Yazawazi) -* [Forrest Sheng Bao](https://forrestbao.github.io/) +hello at funix dot io