Spaces:
Sleeping
Sleeping
File size: 7,001 Bytes
fcbf0a3 f47e966 9da8a12 f47e966 fcbf0a3 f47e966 fcbf0a3 733bdfd fcbf0a3 9da8a12 fcbf0a3 4100b1a fcbf0a3 9da8a12 fcbf0a3 9da8a12 fcbf0a3 9da8a12 fcbf0a3 9da8a12 fcbf0a3 9da8a12 f61d58e 0002a7f f61d58e 0002a7f f61d58e fcbf0a3 e6ba032 fcbf0a3 e6ba032 fcbf0a3 69c11c4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
import uuid
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
from fastapi.middleware.cors import CORSMiddleware
from langchain_core.messages import BaseMessage, HumanMessage, trim_messages
from langchain_core.tools import tool
from langchain_openai import ChatOpenAI
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent
from pydantic import BaseModel
from typing import Optional
import json
from sse_starlette.sse import EventSourceResponse
import io
import sys
from contextlib import redirect_stdout, redirect_stderr
from langchain_core.runnables import RunnableConfig
import requests
import uvicorn
import re
from fastapi.staticfiles import StaticFiles
from langchain_core.runnables import RunnableConfig
from langchain_core.prompts import ChatPromptTemplate
from datetime import datetime
app = FastAPI()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.mount("/chatui", StaticFiles(directory="static/chatui", html=True), name="index")
class CodeExecutionResult:
def __init__(self, output: str, error: str = None):
self.output = output
self.error = error
API_URL = "https://pvanand-code-execution-files-v5.hf.space"
@tool
def execute_python(code: str, config: RunnableConfig):
"""Execute Python code in an IPython interactiveshell and return the output.
The returned artifacts (if present) are automatically rendered in the UI and visible to the user.
Args:
code: Valid Python code with correct indentation and syntax including necessary imports.
Available Libraries:
# Use Plotly for creating visualizations
plotly
pandas
groq
yfinance
numpy
seaborn
numpy
scikit-learn
statsmodels
geopandas
folium
fpdf
kaleido
scipy
geopy
mapbox
"""
#print(config)
headers = {
'accept': 'application/json',
'Content-Type': 'application/json'
}
data = {
"session_token": "test12345", #config.configurable.get("thread_id", "test"),
"code": code
}
response = requests.post(
f'{API_URL}/v0/execute',
headers=headers,
data=json.dumps(data)
)
if response.status_code != 200:
return f"Error: Request failed with status code {response.status_code}. Response: {response.text}"
else:
response_json = response.json()
return f"data: {json.dumps(response_json)} \ndata:"
# Configure the memory and model"
memory = MemorySaver()
model = ChatOpenAI(model="gpt-4o-mini", streaming=True)
prompt = ChatPromptTemplate.from_messages([
("system", f"You are a Data Visualization assistant.You have access to a jupyter client with access to internet for python code execution.\
Your taks is to assist users with your data analysis and visualization expertise. Use Plotly for creating visualizations. Today's date is \
{datetime.now().strftime('%Y-%m-%d')}. The current folder contains the following files: {{collection_files}}"),
("placeholder", "{messages}"),
])
def state_modifier(state) -> list[BaseMessage]:
collection_files = "None"
try:
formatted_prompt = prompt.invoke({
"collection_files": collection_files,
"messages": state["messages"]
})
print(state["messages"])
return trim_messages(
formatted_prompt,
token_counter=len,
max_tokens=16000,
strategy="last",
start_on="human",
include_system=True,
allow_partial=False,
)
except Exception as e:
print(f"Error in state modifier: {str(e)}")
return state["messages"]
# Create the agent with the Python execution tool
agent = create_react_agent(
model,
tools=[execute_python],
checkpointer=memory,
state_modifier=state_modifier,
)
class ChatInput(BaseModel):
message: str
thread_id: Optional[str] = None
@app.post("/chat")
async def chat(input_data: ChatInput):
thread_id = input_data.thread_id or str(uuid.uuid4())
config = {
"configurable": {
"thread_id": thread_id
}
}
input_message = HumanMessage(content=input_data.message)
try:
async def generate():
async for event in agent.astream_events(
{"messages": [input_message]},
config,
version="v2"
):
kind = event["event"]
if kind == "on_chat_model_stream":
content = event["data"]["chunk"].content
if content:
yield f"{json.dumps({'type': 'token', 'content': content})}\n"
if kind == "on_tool_start":
print(f"Debug - Tool being called: {event['name']}") # Add this debug line
tool_input = event['data'].get('input', '')
yield f"{json.dumps({'type': 'tool_start', 'tool': event['name'], 'input': tool_input})}\n"
elif kind == "on_tool_end":
tool_output = event['data'].get('output', '').content
#print(type(tool_output))
#print(dir(tool_output))
#print the keys
pattern = r'data: (.*?)\ndata:'
match = re.search(pattern, tool_output)
print(tool_output)
if match:
tool_output_json = match.group(1).strip()
try:
tool_output = json.loads(tool_output_json)
if "artifacts" in tool_output:
for artifact in tool_output["artifacts"]:
artifact_content = requests.get(f"{API_URL}/artifact/{artifact['artifact_id']}").content
print(artifact_content)
tool_output["artifacts"][artifact["artifact_id"]] = artifact_content
except Exception as e:
print(e)
print("Error parsing tool output as json: ", tool_output)
else:
print("No match found in tool output")
yield f"{json.dumps({'type': 'tool_end', 'tool': event['name'], 'output': tool_output})}\n"
return EventSourceResponse(
generate(),
media_type="text/event-stream"
)
except Exception as e:
print(f"Error during event streaming: {str(e)}")
yield f"{json.dumps({'type': 'error', 'content': str(e)})}\n"
@app.get("/health")
async def health_check():
return {"status": "healthy"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=7860) |