⛓️ Langflow 集成

LangflowGitHub)是 LangChain 的 UI,基于 react-flow 设计,让你能轻松地实验和构建 flow 原型。

通过原生集成(自 langflow v1.0.17 起),你可以用 Langflow 在低代码环境中快速搭建复杂 LLM 应用,再用 Litefuse 监控并改进它们。

集成

视频 指南:如何把 Langflow 与 Litefuse 集成(由 Langflow 发布)

获取 Litefuse API Key

  1. cloud.litefuse.ai 上创建账号和项目
  2. 复制项目的 API Key

配置 Langflow

# API keys from project settings in Langfuse
export LANGFUSE_SECRET_KEY=sk-lf...
export LANGFUSE_PUBLIC_KEY=pk-lf...
 
export LANGFUSE_HOST="https://litefuse.cloud"
# export LANGFUSE_HOST="http://localhost:3000" # 🏠 for self-hosters
 
# Install Langflow
pip install langflow
 
# Start Langflow in the same terminal or environment where you set the environment variables:
python -m langflow run

或者,在设置好环境变量后直接运行 Langflow CLI 命令:

LANGFUSE_SECRET_KEY=secret_key LANGFUSE_PUBLIC_KEY=public_key LANGFUSE_HOST="http://localhost:3000" langflow

在 Litefuse 中查看 trace

现在,当你使用 Langflow 的聊天或 API 时,可以在 Litefuse 中查看对话的 trace。

Langflow traces in Litefuse

Litefuse UI 中的 Langflow 示例 trace

用 Docker Compose 同时运行 Litefuse 和 Langflow

如果你倾向于自托管 Litefuse,可以用 Docker Compose 同时运行这两个服务。合并两份 docker-compose 文件可以简化它们之间的网络配置。

version: "3.5"
 
services:
  # Adapted from https://github.com/logspace-ai/langflow/blob/dev/docker_example/docker-compose.yml
  langflow:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "7860:7860"
    environment:
+     # Tokens are to be created in Litefuse, then copy-pasted here. Then restart docker-compose.
+     - LANGFUSE_SECRET_KEY=sk-lf-...
+     - LANGFUSE_PUBLIC_KEY=pk-lf-...
+     - LANGFUSE_HOST="http://langfuse-server:3000"
    command: langflow run --host 0.0.0.0
 
  # https://github.com/litefuse/litefuse/blob/main/docker-compose.yml
  litefuse-worker:
    image: litefuse/litefuse-worker:3
    restart: always
    depends_on: &litefuse-depends-on
      postgres:
        condition: service_healthy
      minio:
        condition: service_healthy
      redis:
        condition: service_healthy
      doris_fe:
        condition: service_healthy
      doris_be:
        condition: service_healthy
    ports:
      - 127.0.0.1:3030:3030
    environment: &litefuse-worker-env
      NEXTAUTH_URL: http://localhost:3000
      DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres # CHANGEME
      SALT: "mysalt" # CHANGEME
      ENCRYPTION_KEY: "0000000000000000000000000000000000000000000000000000000000000000" # CHANGEME: generate via `openssl rand -hex 32`
      TELEMETRY_ENABLED: ${TELEMETRY_ENABLED:-true}
      LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES: ${LANGFUSE_ENABLE_EXPERIMENTAL_FEATURES:-true}
      # Note: Doris is enabled automatically when LANGFUSE_ANALYTICS_BACKEND="doris"
      LANGFUSE_ANALYTICS_BACKEND: ${LANGFUSE_ANALYTICS_BACKEND:-doris}
      DORIS_URL: ${DORIS_FE_HTTP_URL:-}
      DORIS_FE_HTTP_URL: ${DORIS_FE_HTTP_URL:-http://172.30.0.2:8030}
      DORIS_FE_QUERY_PORT: ${DORIS_FE_QUERY_PORT:-9030}
      DORIS_DB: ${DORIS_DB:-langfuse}
      DORIS_USER: ${DORIS_USER:-root}
      DORIS_PASSWORD: ${DORIS_PASSWORD:-}
      DORIS_MAX_OPEN_CONNECTIONS: ${DORIS_MAX_OPEN_CONNECTIONS:-100}
      DORIS_REQUEST_TIMEOUT_MS: ${DORIS_REQUEST_TIMEOUT_MS:-30000}
      HOSTNAME: "0.0.0.0"
      PORT: "3000"
      LANGFUSE_S3_EVENT_UPLOAD_BUCKET: ${LANGFUSE_S3_EVENT_UPLOAD_BUCKET:-langfuse}
      LANGFUSE_S3_EVENT_UPLOAD_REGION: ${LANGFUSE_S3_EVENT_UPLOAD_REGION:-auto}
      LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID: ${LANGFUSE_S3_EVENT_UPLOAD_ACCESS_KEY_ID:-minio}
      LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_S3_EVENT_UPLOAD_SECRET_ACCESS_KEY:-miniosecret} # CHANGEME
      LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT: ${LANGFUSE_S3_EVENT_UPLOAD_ENDPOINT:-http://minio:9000}
      LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE: ${LANGFUSE_S3_EVENT_UPLOAD_FORCE_PATH_STYLE:-true}
      LANGFUSE_S3_EVENT_UPLOAD_PREFIX: ${LANGFUSE_S3_EVENT_UPLOAD_PREFIX:-events/}
      LANGFUSE_S3_MEDIA_UPLOAD_BUCKET: ${LANGFUSE_S3_MEDIA_UPLOAD_BUCKET:-langfuse}
      LANGFUSE_S3_MEDIA_UPLOAD_REGION: ${LANGFUSE_S3_MEDIA_UPLOAD_REGION:-auto}
      LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID: ${LANGFUSE_S3_MEDIA_UPLOAD_ACCESS_KEY_ID:-minio}
      LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY: ${LANGFUSE_S3_MEDIA_UPLOAD_SECRET_ACCESS_KEY:-miniosecret} # CHANGEME
      LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT: ${LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT:-http://localhost:9090}
      LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE: ${LANGFUSE_S3_MEDIA_UPLOAD_FORCE_PATH_STYLE:-true}
      LANGFUSE_S3_MEDIA_UPLOAD_PREFIX: ${LANGFUSE_S3_MEDIA_UPLOAD_PREFIX:-media/}
      LANGFUSE_S3_BATCH_EXPORT_ENABLED: ${LANGFUSE_S3_BATCH_EXPORT_ENABLED:-false}
      LANGFUSE_S3_BATCH_EXPORT_BUCKET: ${LANGFUSE_S3_BATCH_EXPORT_BUCKET:-langfuse}
      LANGFUSE_S3_BATCH_EXPORT_PREFIX: ${LANGFUSE_S3_BATCH_EXPORT_PREFIX:-exports/}
      LANGFUSE_S3_BATCH_EXPORT_REGION: ${LANGFUSE_S3_BATCH_EXPORT_REGION:-auto}
      LANGFUSE_S3_BATCH_EXPORT_ENDPOINT: ${LANGFUSE_S3_BATCH_EXPORT_ENDPOINT:-http://minio:9000}
      LANGFUSE_S3_BATCH_EXPORT_EXTERNAL_ENDPOINT: ${LANGFUSE_S3_BATCH_EXPORT_EXTERNAL_ENDPOINT:-http://localhost:9090}
      LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID: ${LANGFUSE_S3_BATCH_EXPORT_ACCESS_KEY_ID:-minio}
      LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY: ${LANGFUSE_S3_BATCH_EXPORT_SECRET_ACCESS_KEY:-miniosecret} # CHANGEME
      LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE: ${LANGFUSE_S3_BATCH_EXPORT_FORCE_PATH_STYLE:-true}
      LANGFUSE_INGESTION_QUEUE_DELAY_MS: ${LANGFUSE_INGESTION_QUEUE_DELAY_MS:-}
      LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS: ${LANGFUSE_INGESTION_CLICKHOUSE_WRITE_INTERVAL_MS:-}
      REDIS_HOST: ${REDIS_HOST:-redis}
      REDIS_PORT: ${REDIS_PORT:-6379}
      REDIS_AUTH: ${REDIS_AUTH:-myredissecret} # CHANGEME
      REDIS_TLS_ENABLED: ${REDIS_TLS_ENABLED:-false}
      REDIS_TLS_CA: ${REDIS_TLS_CA:-/certs/ca.crt}
      REDIS_TLS_CERT: ${REDIS_TLS_CERT:-/certs/redis.crt}
      REDIS_TLS_KEY: ${REDIS_TLS_KEY:-/certs/redis.key}
 
  litefuse-web:
    image: litefuse/litefuse:3
    restart: always
    depends_on: *litefuse-depends-on
    ports:
      - 3000:3000
    environment:
      <<: *litefuse-worker-env
      NEXTAUTH_SECRET: mysecret # CHANGEME
      LANGFUSE_INIT_ORG_ID: ${LANGFUSE_INIT_ORG_ID:-}
      LANGFUSE_INIT_ORG_NAME: ${LANGFUSE_INIT_ORG_NAME:-}
      LANGFUSE_INIT_PROJECT_ID: ${LANGFUSE_INIT_PROJECT_ID:-}
      LANGFUSE_INIT_PROJECT_NAME: ${LANGFUSE_INIT_PROJECT_NAME:-}
      LANGFUSE_INIT_PROJECT_PUBLIC_KEY: ${LANGFUSE_INIT_PROJECT_PUBLIC_KEY:-}
      LANGFUSE_INIT_PROJECT_SECRET_KEY: ${LANGFUSE_INIT_PROJECT_SECRET_KEY:-}
      LANGFUSE_INIT_USER_EMAIL: ${LANGFUSE_INIT_USER_EMAIL:-}
      LANGFUSE_INIT_USER_NAME: ${LANGFUSE_INIT_USER_NAME:-}
      LANGFUSE_INIT_USER_PASSWORD: ${LANGFUSE_INIT_USER_PASSWORD:-}
 
  doris_fe:
    image: apache/doris:fe-2.1.11
    hostname: doris_fe
    container_name: doris_fe
    environment:
      - FE_SERVERS=fe1:172.30.0.2:9010
      - FE_ID=1
    ports:
      - "8030:8030"
      - "9030:9030"
      - "9010:9010"
    networks:
      doris_internal:
        ipv4_address: 172.30.0.2
    volumes:
      - doris_fe_meta:/opt/apache-doris/fe/doris-meta
#      - ./doris-config/fe_custom.conf:/opt/apache-doris/fe/conf/fe_custom.conf:ro
    healthcheck:
      test: [ "CMD-SHELL", "mysql -h 127.0.0.1 -P 9030 -uroot -e 'SELECT 1' 2>/dev/null || exit 1" ]
      interval: 10s
      timeout: 5s
      retries: 18
      start_period: 120s
 
  doris_be:
    image: apache/doris:be-2.1.11
    hostname: doris_be
    container_name: doris_be
    environment:
      - FE_SERVERS=fe1:172.30.0.2:9010
      - BE_ADDR=172.30.0.3:9050
    depends_on:
      doris_fe:
        condition: service_healthy
    ports:
      - "8040:8040"
      - "8060:8060"
      - "9050:9050"
      - "9060:9060"
    networks:
      doris_internal:
        ipv4_address: 172.30.0.3
    volumes:
      - doris_be_storage:/opt/apache-doris/be/storage
      # - ./be_custom.conf:/opt/apache-doris/be/conf/be_custom.conf:ro
    restart: unless-stopped
    healthcheck:
      test: [ "CMD-SHELL", "mysql -h 172.30.0.2 -P 9030 -uroot -e 'SHOW BACKENDS\\G' | grep -A 20 'Host: 172.30.0.3' | grep -q 'Alive: true'" ]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 150s
 
  minio:
    image: minio/minio
    restart: always
    entrypoint: sh
    # create the 'langfuse' bucket before starting the service
    command: -c 'mkdir -p /data/langfuse && minio server --address ":9000" --console-address ":9001" /data'
    environment:
      MINIO_ROOT_USER: minio
      MINIO_ROOT_PASSWORD: miniosecret # CHANGEME
    ports:
      - 9090:9000
      - 127.0.0.1:9091:9001
    volumes:
      - langfuse_minio_data:/data
    healthcheck:
      test: ["CMD", "mc", "ready", "local"]
      interval: 1s
      timeout: 5s
      retries: 5
      start_period: 1s
 
  redis:
    image: redis:7
    restart: always
    # CHANGEME: row below to secure redis password
    command: >
      --requirepass ${REDIS_AUTH:-myredissecret}
    ports:
      - 127.0.0.1:6379:6379
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 3s
      timeout: 10s
      retries: 10
 
  postgres:
    image: postgres:${POSTGRES_VERSION:-latest}
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 3s
      timeout: 3s
      retries: 10
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres # CHANGEME
      POSTGRES_DB: postgres
    ports:
      - 127.0.0.1:5432:5432
    volumes:
      - langfuse_postgres_data:/var/lib/postgresql/data
 
volumes:
  langfuse_postgres_data:
    driver: local
  langfuse_minio_data:
    driver: local
  doris_fe_meta:
    driver: local
  doris_be_storage:
    driver: local

用以下命令测试 Langflow 与 Litefuse 之间的连通性:

docker compose exec langflow python -c "import requests, os; addr = os.environ.get('LANGFUSE_HOST'); print(addr); res = requests.get(addr, timeout=5); print(res.status_code)"
 
# 应输出如下内容:
# http://litefuse-server:3000
# 200
这个页面对你有帮助吗?