fixing everything
Browse files- Dockerfile +10 -15
- app.py +34 -26
- state.py +12 -0
Dockerfile
CHANGED
@@ -1,23 +1,18 @@
|
|
1 |
-
# Use official Python 3.9 image
|
2 |
FROM python:3.9
|
3 |
-
|
4 |
-
# Create and use a non-root user
|
5 |
RUN useradd -m -u 1000 user
|
6 |
USER user
|
7 |
-
|
8 |
-
# Define environment variables
|
9 |
ENV HOME=/home/user \
|
10 |
-
PATH=/home/user/.local/bin:$PATH
|
11 |
-
PYTHONPATH=/home/user/app
|
12 |
-
|
13 |
-
# Set working directory
|
14 |
WORKDIR $HOME/app
|
15 |
|
16 |
-
# Copy
|
17 |
-
COPY --chown=user .
|
|
|
|
|
|
|
|
|
18 |
|
19 |
-
|
20 |
-
|
21 |
|
22 |
-
|
23 |
-
CMD ["chainlit", "run", "app.py", "--port", "7860"]
|
|
|
|
|
1 |
FROM python:3.9
|
|
|
|
|
2 |
RUN useradd -m -u 1000 user
|
3 |
USER user
|
|
|
|
|
4 |
ENV HOME=/home/user \
|
5 |
+
PATH=/home/user/.local/bin:$PATH
|
|
|
|
|
|
|
6 |
WORKDIR $HOME/app
|
7 |
|
8 |
+
# Copy requirements first for better caching
|
9 |
+
COPY --chown=user requirements.txt .
|
10 |
+
RUN pip install -r requirements.txt
|
11 |
+
|
12 |
+
# Copy the rest of the application
|
13 |
+
COPY --chown=user . .
|
14 |
|
15 |
+
ENV PYTHONUNBUFFERED=1
|
16 |
+
EXPOSE 7860
|
17 |
|
18 |
+
CMD ["chainlit", "run", "app.py", "--host", "0.0.0.0", "--port", "7860"]
|
|
app.py
CHANGED
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
2 |
import os
|
3 |
import chainlit as cl
|
4 |
import pandas as pd
|
5 |
-
from typing import List, Dict, Any, TypedDict, Callable, Annotated, Literal, Optional, Union, Tuple
|
6 |
from qdrant_client import QdrantClient
|
7 |
from qdrant_client.models import Distance, VectorParams, PointStruct
|
8 |
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
@@ -20,6 +20,8 @@ from langchain_core.runnables import RunnableConfig
|
|
20 |
from langchain_core.runnables.utils import Output
|
21 |
from langchain_core.output_parsers import StrOutputParser
|
22 |
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
|
|
|
|
23 |
|
24 |
# Load environment variables
|
25 |
load_dotenv()
|
@@ -40,17 +42,7 @@ SIMILARITY_THRESHOLD = 0.75
|
|
40 |
DEFAULT_TIMEOUT = 60 # Default timeout in seconds
|
41 |
API_RATE_LIMIT_DELAY = 1 # Delay between API calls in seconds
|
42 |
|
43 |
-
|
44 |
-
class FounderAnalysisState(TypedDict):
|
45 |
-
query: str
|
46 |
-
query_type: str # "search" or "filter"
|
47 |
-
filter_key: str
|
48 |
-
filter_value: str
|
49 |
-
retrieved_profiles: List[Dict[str, Any]]
|
50 |
-
web_search_results: List[Dict[str, Any]]
|
51 |
-
analysis_results: List[Dict[str, Any]]
|
52 |
-
final_response: Dict[str, Any]
|
53 |
-
error: str
|
54 |
|
55 |
# Decorator for adding timeouts to async functions
|
56 |
def async_timeout(timeout_seconds=DEFAULT_TIMEOUT):
|
@@ -142,8 +134,8 @@ class FounderAnalysisSystem:
|
|
142 |
|
143 |
def _create_workflow(self) -> StateGraph:
|
144 |
"""Create the LangGraph workflow for founder analysis."""
|
145 |
-
#
|
146 |
-
workflow = StateGraph(
|
147 |
|
148 |
# Add nodes to the graph
|
149 |
workflow.add_node("process_query", self.process_query)
|
@@ -190,6 +182,22 @@ class FounderAnalysisSystem:
|
|
190 |
@async_timeout(30) # 30 second timeout for query processing
|
191 |
async def process_query(self, state: FounderAnalysisState) -> FounderAnalysisState:
|
192 |
"""Process the user query and determine the query type."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
193 |
query = state["query"]
|
194 |
|
195 |
# Log the processing step
|
@@ -616,18 +624,18 @@ class FounderAnalysisSystem:
|
|
616 |
# Reset progress message
|
617 |
self.progress_message = None
|
618 |
|
619 |
-
# Initialize the state
|
620 |
-
state =
|
621 |
-
query
|
622 |
-
query_type
|
623 |
-
filter_key
|
624 |
-
filter_value
|
625 |
-
retrieved_profiles
|
626 |
-
web_search_results
|
627 |
-
analysis_results
|
628 |
-
final_response
|
629 |
-
error
|
630 |
-
|
631 |
|
632 |
try:
|
633 |
# Manually execute the workflow nodes in sequence
|
|
|
2 |
import os
|
3 |
import chainlit as cl
|
4 |
import pandas as pd
|
5 |
+
from typing import List, Dict, Any, TypedDict, Callable, Annotated, Literal, Optional, Union, Tuple, TypeVar
|
6 |
from qdrant_client import QdrantClient
|
7 |
from qdrant_client.models import Distance, VectorParams, PointStruct
|
8 |
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
|
|
|
20 |
from langchain_core.runnables.utils import Output
|
21 |
from langchain_core.output_parsers import StrOutputParser
|
22 |
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
23 |
+
from dataclasses import dataclass, field
|
24 |
+
from state import FounderAnalysisState
|
25 |
|
26 |
# Load environment variables
|
27 |
load_dotenv()
|
|
|
42 |
DEFAULT_TIMEOUT = 60 # Default timeout in seconds
|
43 |
API_RATE_LIMIT_DELAY = 1 # Delay between API calls in seconds
|
44 |
|
45 |
+
StateType = TypeVar("StateType", bound=Dict[str, Any])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
# Decorator for adding timeouts to async functions
|
48 |
def async_timeout(timeout_seconds=DEFAULT_TIMEOUT):
|
|
|
134 |
|
135 |
def _create_workflow(self) -> StateGraph:
|
136 |
"""Create the LangGraph workflow for founder analysis."""
|
137 |
+
# Use a simple dict type for the state graph
|
138 |
+
workflow = StateGraph(dict)
|
139 |
|
140 |
# Add nodes to the graph
|
141 |
workflow.add_node("process_query", self.process_query)
|
|
|
182 |
@async_timeout(30) # 30 second timeout for query processing
|
183 |
async def process_query(self, state: FounderAnalysisState) -> FounderAnalysisState:
|
184 |
"""Process the user query and determine the query type."""
|
185 |
+
# Initialize state if needed
|
186 |
+
if not isinstance(state, dict):
|
187 |
+
state = {}
|
188 |
+
|
189 |
+
state.update({
|
190 |
+
"query": state.get("query", ""),
|
191 |
+
"query_type": "",
|
192 |
+
"filter_key": "",
|
193 |
+
"filter_value": "",
|
194 |
+
"retrieved_profiles": [],
|
195 |
+
"web_search_results": [],
|
196 |
+
"analysis_results": [],
|
197 |
+
"final_response": {},
|
198 |
+
"error": ""
|
199 |
+
})
|
200 |
+
|
201 |
query = state["query"]
|
202 |
|
203 |
# Log the processing step
|
|
|
624 |
# Reset progress message
|
625 |
self.progress_message = None
|
626 |
|
627 |
+
# Initialize the state as a simple dictionary
|
628 |
+
state = {
|
629 |
+
"query": query,
|
630 |
+
"query_type": "",
|
631 |
+
"filter_key": "",
|
632 |
+
"filter_value": "",
|
633 |
+
"retrieved_profiles": [],
|
634 |
+
"web_search_results": [],
|
635 |
+
"analysis_results": [],
|
636 |
+
"final_response": {},
|
637 |
+
"error": ""
|
638 |
+
}
|
639 |
|
640 |
try:
|
641 |
# Manually execute the workflow nodes in sequence
|
state.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from typing import TypedDict, List, Dict, Any
|
2 |
+
|
3 |
+
class FounderAnalysisState(TypedDict, total=False):
|
4 |
+
query: str
|
5 |
+
query_type: str
|
6 |
+
filter_key: str
|
7 |
+
filter_value: str
|
8 |
+
retrieved_profiles: List[Dict[str, Any]]
|
9 |
+
web_search_results: List[Dict[str, Any]]
|
10 |
+
analysis_results: List[Dict[str, Any]]
|
11 |
+
final_response: Dict[str, Any]
|
12 |
+
error: str
|