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
相关产品推荐
相关产品推荐

