You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Streamlit嵌入FastAPI知识图谱应用:IFrame显示空白问题求助

问题:Streamlit嵌入FastAPI应用显示空白页面

我有一个包含3个简单机器学习应用页面的Streamlit项目,同时维护一个独立的FastAPI应用——基于GPT-3.5 16k模型,以自有文档为上下文生成知识图谱。

我希望将这个知识图谱应用作为Streamlit的一个页面集成(用于展示,提升可读性),由于它有独立UI,计划通过IFrame嵌入显示。

目前知识图谱应用可在localhost:8080正常访问,但将其作为页面添加到localhost:8501的Streamlit应用后,访问该图谱页面时仅显示空白,无任何UI内容。

所有容器运行状态正常,执行docker exec -it streamlit-ui curl http://graph-ui:8080可成功获取FastAPI应用的内容;即使替换API_HOST为其他外部链接,Streamlit的IFrame仍然无法显示内容,因此问题并非出在知识图谱应用本身。


Streamlit图谱页面代码

import os
import streamlit as st

API_HOST = "http://graph_container_name:8080"

def app():
    st.title("FastAPI Integration with Streamlit")
    
    # Adding an iframe component embedding the FastAPI application.
    st.markdown(f'<iframe src="{API_HOST}" width="100%" height="600"></iframe>', unsafe_allow_html=True)

FastAPI应用代码(graph/main.py)

import os
import json
from dotenv import load_dotenv
import openai
import requests
from bs4 import BeautifulSoup
from graphviz import Digraph
from fastapi import FastAPI, HTTPException, Request, Depends
from fastapi.templating import Jinja2Templates
from fastapi.responses import JSONResponse, HTMLResponse
from pydantic import BaseModel

from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()


app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)



templates = Jinja2Templates(directory="templates")

ENV_FILE = ".env"
load_dotenv(ENV_FILE)

# Set your OpenAI API key
openai.api_key = os.getenv("OPENAI_API_KEY")
response_data = ""


# Function to scrape text from a website
def scrape_text_from_url(url: str) -> str:
    response = requests.get(url)
    if response.status_code != 200:
        return "Error: Could not retrieve content from URL."
    soup = BeautifulSoup(response.text, 'html.parser')
    paragraphs = soup.find_all('p')
    text = ' '.join([p.get_text() for p in paragraphs])
    print("web scrape done")
    return text


class InputData(BaseModel):
    user_input: str


@app.post("/get_response_data")
def get_response_data(data: InputData):
    global response_data

    if not data.user_input:
        raise HTTPException(status_code=400, detail="No input provided")
    print("starting openai call")
    completion = openai.ChatCompletion.create(
        model="gpt-3.5-turbo-16k",
        messages=[
            {
                "role": "user",
                "content": f"Help me understand following by describing as a detailed knowledge graph: {data.user_input}"

            }
        ],
        functions=[
            {
                "name": "knowledge_graph",
                "description": "Generate a knowledge graph with entities and relationships. Use the colors to help differentiate between different node or edge types/categories. Always provide light pastel colors that work well with black font.",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "metadata": {
                            "type": "object",
                            "properties": {
                                "createdDate": {"type": "string"},
                                "lastUpdated": {"type": "string"},
                                "description": {"type": "string"}
                            }
                        },
                        "nodes": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "id": {"type": "string"},
                                    "label": {"type": "string"},
                                    "type": {"type": "string"},
                                    "color": {"type": "string"},  # Added color property
                                    "properties": {
                                        "type": "object",
                                        "description": "Additional attributes for the node"
                                    }
                                },
                                "required": ["id", "label", "type", "color"]  # Added color to required
                            }
                        },
                        "edges": {
                            "type": "array",
                            "items": {
                                "type": "object",
                                "properties": {
                                    "from": {"type": "string"},
                                    "to": {"type": "string"},
                                    "relationship": {"type": "string"},
                                    "direction": {"type": "string"},
                                    "color": {"type": "string"},  # Added color property
                                    "properties": {
                                        "type": "object",
                                        "description": "Additional attributes for the edge"
                                    }
                                },
                                "required": ["from", "to", "relationship", "color"]  # Added color to required
                            }
                        }
                    },
                    "required": ["nodes", "edges"],
                },
            }
        ],
        function_call={"name": "knowledge_graph"}
    )
    
    response_data = completion.choices[0]['message']['function_call']['arguments']
    print(response_data)
    return response_data


@app.post("/graphviz")
def visualize_knowledge_graph_with_graphviz(request: Request):

    global response_data
    dot = Digraph(comment='Knowledge Graph')
    response_dict = json.loads(response_data)
    
    # Add nodes to the graph
    for node in response_dict.get('nodes', []):
        dot.node(node['id'], f"{node['label']} ({node['type']})")
        
    # Add edges to the graph
    for edge in response_dict.get('edges', []):
        dot.edge(edge['from'], edge['to'], label=edge['relationship'])
    
    # Render and visualize
    dot.render('knowledge_graph.gv', view=False)
    # Render to PNG format and save it
    dot.format = 'png'
    dot.render('static/knowledge_graph', view=False)
  
    # Construct the URL pointing to the generated PNG
    png_url = f"{request.url_root}static/knowledge_graph.png"
    
    return JSONResponse(content={"png_url": png_url})



@app.post("/get_graph_data")
def get_graph_data():
    global response_data
    try:
        print(response_data)
        response_dict = json.loads(response_data)

        nodes = [{"data": {"id": node["id"], "label": node["label"], "color": node.get("color", "defaultColor")}} for node in response_dict["nodes"]]
        edges = [{"data": {"source": edge["from"], "target": edge["to"], "label": edge["relationship"], "color": edge.get("color", "defaultColor")}} for edge in response_dict["edges"]]
        return JSONResponse(content={"elements": {"nodes": nodes, "edges": edges}})

    except Exception as e:
        # This captures all exceptions and sends back an empty graph. 
        # For better debugging, you can print the exception or save it to logs.
        print(str(e))
        return JSONResponse(content={"elements": {"nodes": [], "edges": []}})


@app.get("/", response_class=HTMLResponse)
def read_root(request: Request):
    return templates.TemplateResponse("index.html", {"request": request})


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host='0.0.0.0', port=8080)

Graph服务Dockerfile

FROM python:3.11.4-slim-bullseye

WORKDIR /app

COPY requirements.txt /app/requirements.txt

RUN apt-get update -y && apt-get install -y pkg-config gcc


RUN pip3 install --no-cache-dir -r requirements.txt

RUN pip install -U matplotlib

COPY . .

CMD ["python", "main.py"]

Streamlit服务Dockerfile

FROM python:3.11.4-slim-bullseye

WORKDIR /app

COPY streamlit_ui/requirements.txt /app/requirements.txt
COPY graph/requirements.txt /app/graph_requirements.txt

RUN apt-get update -y

RUN pip3 install --no-cache-dir -r requirements.txt
RUN pip3 install --no-cache-dir -r graph_requirements.txt

COPY streamlit_ui/ .
COPY graph/ /app/graph/

CMD ["streamlit", "run", "App.py", "--server.port", "8501"]

docker-compose.yaml片段

llm-s:
    build:
      context: llm_s
      dockerfile: Dockerfile
    container_name: llm-s
    ports:
      - "8000:8000"
    environment:

    depends_on:
      - "standalone"
    networks:
      - llm_network

  streamlit-ui:
    build:
      context: .
      dockerfile: streamlit_ui/Dockerfile
    container_name: streamlit-ui
    ports:
      - "8501:8501"
    environment:
      - API_NETWORK_HOST=http://myapi:8000
    depends_on:
      - "llm-s"
    networks:
      - llm_network

  graph:
    build:
      context: ./graph
      dockerfile: Dockerfile
    container_name: graph-ui
    ports:
      - "8080:8080"
    environment:
      - API_NETWORK_HOST=graph-ui:8080
    depends_on:
      - "llm-s"
    networks:
      - llm_network



networks:
  llm_network:
    driver: bridge

内容的提问来源于stack exchange,提问作者tbo812

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 12:45:55