Morphでは、Pythonを使用してバックエンドを構築します。Pythonパッケージを自由に追加して、データ処理やAIワークフローを構築することができます。

開発の流れ

Morphでのバックエンド開発の手順は以下の通りです。

1

Pythonパッケージを追加する

Morphは一般的なPythonプロジェクトの形式であるため、自由にPythonパッケージを追加することができます。requirements.txtpyproject.tomlに必要なパッケージを追加してください。

2

Python関数を定義し、Morphのデコレーターを追加

通常のPythonの関数定義に、Morphのデコレーターを追加することで、エイリアスを設定します。これにより、他のPythonやSQLファイル、マークダウンファイルからこの関数の結果を参照することができます。

import pandas as pd
import morph
from morph import MorphGlobalContext

# Morphのデコレーターを追加
@morph.func(name="example_dataframe")
@morph.load_data("example_data")
def example_dataframe(context: MorphGlobalContext):
    df = context.data["example_data"]
    return df
3

Python関数をテストする

関数を単体テストするために、morph runコマンドを使用して関数を実行します。

morph run example_dataframe
4

開発サーバーを起動する

開発サーバーを起動することで、Webアプリケーションをローカルで確認することができます。

morph serve

Python関数の返り値

Morphプロジェクトで定義するPython関数は、以下のような返り値を持つ必要があります。

DataFrame

データ処理の結果を表すDataFrameオブジェクト。SQLの実行結果もDataFrameとして扱われます。データ処理の結果を他のPythonファイルで用いる場合や、マークダウンファイルで表示する場合に使用してください。

対応するマークダウンコンポーネントは、<DataFrame>です。

import morph
from morph import MorphGlobalContext

@morph.func(name="example_dataframe")
@morph.load_data("example_data")
def example_dataframe(context: MorphGlobalContext):
    df = context.data["example_data"]
    return df

HTML文字列

データ可視化の結果などを描画するためのHTML文字列。PlotlyやBokehなどの可視化ライブラリを用いて描画したグラフを表示したい場合に使用してください。

対応するマークダウンコンポーネントは、<Embed>です。

import plotly.express as px
import morph
from morph import MorphGlobalContext
from morph_lib.types import HtmlResponse

@morph.func(name="example_dataframe")
@morph.load_data("example_data")
def example_dataframe(context: MorphGlobalContext):
    df = context.data["example_data"]
    fig = px.bar(df, x='date', y='amount')
    return HtmlResponse(fig.to_html())

ストリーミング

LLM APIなどのストリーミングAPIを使用する場合に使用します。 returnの代わりにyieldを用いて値の流し込みを実行します。

対応するマークダウンコンポーネントは、<Chat>です。

import morph
from morph import MorphGlobalContext
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage

@morph.func
def langchain_chat(context: MorphGlobalContext):
    llm = ChatOpenAI(model="gpt-4o")
    messages = [HumanMessage(context.vars["prompt"])]
    for token in llm.stream(messages):
        yield token.content