feat: Integrate Folk CRM API for investor synchronization and compatibility scoring
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import os
|
||||
from typing import List
|
||||
from typing import List, Optional
|
||||
|
||||
from db.db import DATABASE_URL, get_db
|
||||
from db.models import FundTable, InvestorTable
|
||||
from db.models import FundTable, InvestorTable, ProjectTable
|
||||
from langchain import hub
|
||||
from langchain_community.agent_toolkits import SQLDatabaseToolkit
|
||||
from langchain_community.utilities import SQLDatabase
|
||||
@@ -16,6 +16,8 @@ from schemas.router_schemas import (
|
||||
)
|
||||
from sqlalchemy.orm import selectinload
|
||||
|
||||
from services.compatibility_score import calculate_project_investor_compatibility
|
||||
|
||||
# Connect to SQLite
|
||||
prompt_template = hub.pull("langchain-ai/sql-agent-system-prompt")
|
||||
db = SQLDatabase.from_uri(DATABASE_URL)
|
||||
@@ -44,8 +46,15 @@ class QueryProcessor:
|
||||
prompt=system_message_updated,
|
||||
)
|
||||
|
||||
def process_query(self, question: str) -> PaginatedResponse[InvestmentResponse]:
|
||||
"""Process a query using the LLM and return investment response data."""
|
||||
def process_query(
|
||||
self, question: str, project_id: Optional[int] = None
|
||||
) -> PaginatedResponse[InvestmentResponse]:
|
||||
"""Process a query using the LLM and return investment response data.
|
||||
|
||||
Args:
|
||||
question: The natural language query to process
|
||||
project_id: Optional project ID for compatibility scoring
|
||||
"""
|
||||
# Let the LLM handle all database interactions and filtering to get fund IDs
|
||||
response = self.agent.invoke(
|
||||
{"messages": [("user", question)]},
|
||||
@@ -60,7 +69,7 @@ class QueryProcessor:
|
||||
fund_ids = self._extract_fund_ids_from_response(ai_response)
|
||||
|
||||
# Fetch full fund data with investor relationships using the IDs
|
||||
return self._fetch_funds_by_ids(fund_ids)
|
||||
return self._fetch_funds_by_ids(fund_ids, project_id)
|
||||
|
||||
def _extract_fund_ids_from_response(self, ai_response: str) -> List[int]:
|
||||
"""Extract fund IDs from AI response."""
|
||||
@@ -85,10 +94,15 @@ class QueryProcessor:
|
||||
return fund_ids
|
||||
|
||||
def _fetch_funds_by_ids(
|
||||
self, fund_ids: List[int]
|
||||
self, fund_ids: List[int], project_id: Optional[int] = None
|
||||
) -> PaginatedResponse[InvestmentResponse]:
|
||||
"""Fetch funds with all their relationships from the database using fund IDs.
|
||||
Constructs response similar to read_investors but starting from funds."""
|
||||
Constructs response similar to read_investors but starting from funds.
|
||||
|
||||
Args:
|
||||
fund_ids: List of fund IDs to fetch
|
||||
project_id: Optional project ID for compatibility scoring
|
||||
"""
|
||||
if not fund_ids:
|
||||
return PaginatedResponse(
|
||||
items=[],
|
||||
@@ -102,6 +116,16 @@ class QueryProcessor:
|
||||
db_session = next(get_db())
|
||||
|
||||
try:
|
||||
# Load project if project_id provided
|
||||
project = None
|
||||
if project_id is not None:
|
||||
project = (
|
||||
db_session.query(ProjectTable)
|
||||
.options(selectinload(ProjectTable.sector))
|
||||
.filter(ProjectTable.id == project_id)
|
||||
.first()
|
||||
)
|
||||
|
||||
# Query funds with all necessary relationships loaded
|
||||
funds = (
|
||||
db_session.query(FundTable)
|
||||
@@ -127,6 +151,13 @@ class QueryProcessor:
|
||||
for fund in funds:
|
||||
investor = fund.investor
|
||||
|
||||
# Calculate compatibility score if project provided
|
||||
compatibility_score = 1.0
|
||||
if project is not None:
|
||||
compatibility_score = calculate_project_investor_compatibility(
|
||||
project=project, investor=investor, use_funds=True
|
||||
)
|
||||
|
||||
# Get top 3 portfolio companies (id and name only)
|
||||
portfolio_companies = [
|
||||
CompanyMinimal(id=company.id, name=company.name)
|
||||
@@ -158,7 +189,7 @@ class QueryProcessor:
|
||||
stage_focus=stage_focus,
|
||||
portfolio_companies=portfolio_companies,
|
||||
sectors=fund_sectors,
|
||||
compatibility_score=1.0,
|
||||
compatibility_score=compatibility_score,
|
||||
)
|
||||
investment_responses.append(investment_response)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user