Files
Anton_wireframe/app/services/__pycache__/querying.cpython-312.pyc
T

135 lines
13 KiB
Plaintext
Raw Normal View History

Ë
2025-10-28 21:09:47 +01:00
Ç"iö0ãóàddlZddlZddlZddlZddlmZmZddlmZddl m
Z
2025-10-28 21:09:47 +01:00
m Z m Z ddl
mZddlmZddlmZmZmZmZddlmZdd lmZdd
lmZej8e«ZGd d «Zy)
éN)ÚListÚOptional)Úget_db)Ú FundTableÚ
InvestorTableÚ ProjectTable)ÚChatPromptTemplate)Ú
2025-09-25 17:00:38 +01:00
ChatOpenAI)ÚCompanyMinimalÚInvestmentResponseÚPaginatedResponseÚ
2025-10-28 20:54:15 +01:00
SectorMinimal)Útext)Ú selectinload)Ú(calculate_project_investor_compatibilitycó”eZdZdZdedefdZ d dedeedee fdZ
d dedeedee fdZ d d e edeedee fd
Z
y) ÚQueryProcessorcó˜ttjd«ddd¬«|_i|_t j ddg«|_y)OPENROUTER_API_KEYzhttps://openrouter.ai/api/v1zopenai/gpt-4o-minir)Úapi_keyÚbase_urlÚmodelÚ temperature)Úsystemu%You are a SQL expert. Generate a SQLite query to find fund IDs based on user requirements.
Database Schema:
- funds: id, fund_name, investor_id, check_size_lower, check_size_upper, geographic_focus
- fund_sectors: fund_id, sector_id
2025-10-28 20:54:15 +01:00
- fund_investment_stages: fund_id, stage_id
- sectors: id, name
2025-10-28 21:09:47 +01:00
- investment_stages: id, name
- investors: id, name, aum
IMPORTANT RULES:
1. ALWAYS return ONLY fund IDs (funds.id) - use SELECT DISTINCT f.id
2. For geography: Be FLEXIBLE - use OR with variations and partial matches
- 'Europe' → WHERE geographic_focus LIKE '%Europe%' OR geographic_focus LIKE '%European%'
- 'America' → WHERE geographic_focus LIKE '%America%' OR geographic_focus LIKE '%US%' OR geographic_focus LIKE '%United States%'
- 'Asia' → WHERE geographic_focus LIKE '%Asia%' OR geographic_focus LIKE '%Asian%'
- If no geography specified, DON'T filter by geography
3. For stages: Use LEFT JOIN and LIKE for flexible matching with synonyms
- 'Seed' → s.name LIKE '%Seed%' OR s.name LIKE '%Pre-Seed%' OR s.name LIKE '%Early%'
- 'Series A' → s.name LIKE '%Series A%' OR s.name LIKE '%A%'
- 'Growth' → s.name LIKE '%Growth%' OR s.name LIKE '%Late%' OR s.name LIKE '%Expansion%'
- If stage not specified, include ALL funds
4. For sectors: Use LEFT JOIN and include related terms with OR
- 'Fintech' → sec.name LIKE '%Fintech%' OR sec.name LIKE '%Finance%' OR sec.name LIKE '%Financial%'
2025-10-28 20:54:15 +01:00
- 'AI' → sec.name LIKE '%AI%' OR sec.name LIKE '%Artificial Intelligence%' OR sec.name LIKE '%Machine Learning%' OR sec.name LIKE '%ML%'
2025-10-28 21:09:47 +01:00
- 'Healthcare' → sec.name LIKE '%Healthcare%' OR sec.name LIKE '%Health%' OR sec.name LIKE '%Medical%' OR sec.name LIKE '%Biotech%'
5. For check size filters (be flexible with ranges):
- "under X" → WHERE (check_size_upper <= X OR check_size_upper IS NULL)
- "over X" → WHERE (check_size_lower >= X OR check_size_lower IS NULL)
- "between X and Y" → WHERE check_size_lower >= X AND check_size_upper <= Y
6. Use LEFT JOIN for stages and sectors so funds without tags still match
2025-10-28 20:54:15 +01:00
7. Use DISTINCT to avoid duplicates from joins
8. Be INCLUSIVE - use OR conditions to cast a wider net
9. If query is very simple (e.g., just "seed stage"), don't add unnecessary filters
2025-10-28 21:09:47 +01:00
10. Return a single, complete SELECT query
Example Queries:
Q: "Seed stage investors in Europe"
2025-10-28 20:54:15 +01:00
A: SELECT DISTINCT f.id FROM funds f
LEFT JOIN fund_investment_stages fis ON f.id = fis.fund_id
LEFT JOIN investment_stages s ON fis.stage_id = s.id
2025-10-28 21:09:47 +01:00
WHERE (s.name LIKE '%Seed%' OR s.name LIKE '%Pre-Seed%' OR s.name LIKE '%Early%' OR s.id IS NULL)
AND (f.geographic_focus LIKE '%Europe%' OR f.geographic_focus LIKE '%European%')
Q: "Fintech investors with check size under 5 million"
A: SELECT DISTINCT f.id FROM funds f
LEFT JOIN fund_sectors fs ON f.id = fs.fund_id
LEFT JOIN sectors sec ON fs.sector_id = sec.id
WHERE (sec.name LIKE '%Fintech%' OR sec.name LIKE '%Finance%' OR sec.name LIKE '%Financial%' OR sec.id IS NULL)
AND (f.check_size_upper <= 5000000 OR f.check_size_upper IS NULL)
2025-10-28 20:54:15 +01:00
Q: "Seed stage investors"
A: SELECT DISTINCT f.id FROM funds f
LEFT JOIN fund_investment_stages fis ON f.id = fis.fund_id
2025-10-28 21:09:47 +01:00
LEFT JOIN investment_stages s ON fis.stage_id = s.id
WHERE s.name LIKE '%Seed%' OR s.name LIKE '%Pre-Seed%' OR s.name LIKE '%Early%'
Q: "Growth stage investors"
A: SELECT DISTINCT f.id FROM funds f
LEFT JOIN fund_investment_stages fis ON f.id = fis.fund_id
LEFT JOIN investment_stages s ON fis.stage_id = s.id
WHERE s.name LIKE '%Growth%' OR s.name LIKE '%Late%' OR s.name LIKE '%Expansion%' OR s.name LIKE '%Series C%' OR s.name LIKE '%Series D%'
Q: "AI investors in America"
2025-10-28 20:54:15 +01:00
A: SELECT DISTINCT f.id FROM funds f
2025-10-28 21:09:47 +01:00
LEFT JOIN fund_sectors fs ON f.id = fs.fund_id
2025-10-28 20:54:15 +01:00
LEFT JOIN sectors sec ON fs.sector_id = sec.id
2025-10-28 21:09:47 +01:00
WHERE (sec.name LIKE '%AI%' OR sec.name LIKE '%Artificial Intelligence%' OR sec.name LIKE '%Machine Learning%' OR sec.name LIKE '%ML%')
AND (f.geographic_focus LIKE '%America%' OR f.geographic_focus LIKE '%US%' OR f.geographic_focus LIKE '%United States%' OR f.geographic_focus LIKE '%USA%')
Q: "Healthcare investors"
A: SELECT DISTINCT f.id FROM funds f
2025-10-28 20:54:15 +01:00
LEFT JOIN fund_sectors fs ON f.id = fs.fund_id
LEFT JOIN sectors sec ON fs.sector_id = sec.id
WHERE sec.name LIKE '%Healthcare%' OR sec.name LIKE '%Health%' OR sec.name LIKE '%Medical%' OR sec.name LIKE '%Biotech%' OR sec.name LIKE '%Pharma%'
2025-10-28 21:09:47 +01:00
IMPORTANT: Use LEFT JOIN so funds without sector/stage tags can still match. Include synonym terms with OR for better recall.
Return ONLY the SQL query, no explanations or markdown.)Úuserz
{question})r
ÚosÚgetenvÚllmÚ query_cacher Ú
from_messagesÚ
2025-10-28 20:54:15 +01:00
sql_prompt)Úselfs úL/home/oluwasanmi/Documents/Work/MKD/anton_wireframe/app/services/querying.pyÚ__init__zQueryProcessor.__init__sVÜÜ—Iô 
ˆŒðˆÔôQðd'ðgT
óV
ˆóÚquestionÚreturncóœtj|j«j«j ««j «S)z,Generate cache key from normalized question.)ÚhashlibÚmd5ÚlowerÚstripÚencodeÚ hexdigest)r"r&s r#Ú_get_cache_keyzQueryProcessor._get_cache_key~s3ä{‰{˜8Ÿ>™>Ó+×3×=×Ir%
project_idcƒó`Ktj|j||«ƒd{S7Œ­w)zrAsync wrapper for process_query. Runs blocking work in a thread to avoid
blocking the event loop.
N)ÚasyncioÚ to_threadÚ_process_query_sync)r"r&r0s r#Ú
2025-10-28 21:09:47 +01:00
process_queryzQueryProcessor.process_querys)èø€ô ×& t×'?Ñ'?ÀÈ:ÓV×Vús %.§,¨.c ó2|j|«}||jvr(|j|}tjd|«n¨|jj |¬«}|j j|«}|jj«}|jdd«jdd«j«}||j|<tjd|«tt««} |jt|««}|j«D cgc]} | dŒ }
} tjdt!|
2025-10-28 20:54:15 +01:00
«d |
d
2025-10-28 21:09:47 +01:00
d t!|
«d kDrd nd«|j#|
|«|j%«Scc} w#t&$rZ} tj)d
| «tj)d|«t+gddd d¬«cYd
} ~ |j%«Sd
} ~ wwxYw#|j%«wxYw)zqSynchronous implementation of process_query. This is run in a thread by
the async wrapper above.
zUsing cached SQL: )r&z```sqlÚz```zGenerated SQL: rzFound z fund IDs: Né
z...zSQL execution error: z Failed SQL: é©ÚitemsÚtotalÚpageÚ page_sizeÚ total_pages)r/rÚloggerÚinfor!Úformat_messagesrÚinvokeÚcontentr,ÚreplaceÚnextrÚexecuterÚfetchallÚlenÚ_fetch_funds_by_idsÚcloseÚ ExceptionÚerrorr
) r"r&r0Ú cache_keyÚ sql_queryÚmessagesÚresponseÚ
db_sessionÚresultÚrowÚfund_idsÚes r#r4z"QueryProcessor._process_query_syncŠð ×Ó1ˆ ð ˜× ×Ñ3ˆIÜ K‰KÐ,¨Y¨KÐ ×ÐIˆHØ—x‘x— xÓ0ˆHØ ×(×0ˆ"×)¨(°BÓ7×ÀrÓRˆIð+4ˆD× Ñ ˜ K‰K˜/¨)¨Ð œ&(“^ˆ
ð Ø×¨Y«Ó8ˆFØ*0¯/©/Ó*;Ö< 3˜˜AÐ<ˆ K‰KØœ˜X›˜ {°8¸C¸R°=°/Ì3ÈxË=Ð[]ÒK]Á%ÐceÐAfÐ
ð×+¨H°jÓ
× Ñ Õ ùò=øô ò Ü L‰LаРL‰L˜   ¨°RÀQôô
ð
× Ñ Õ ûð ûð
× Ñ Õ úsCÄ,FÄ0 FÄ<A FÆFÆ HÆ'?G<Ç&HÇ'HÇ<HÈHÈHrUc
óD|s#tgdd|rt|«d¬«Sdd¬«Stt««} d}|i|j t
«j
2025-10-28 21:09:47 +01:00
tt
j««jt
j|k(«j«}|j t«j
ttj«jtj«ttj«jtj «ttj«jtj"«ttj$«ttj"««jtjj'|««j)«}g}|D]o}|j}d} |t+||d¬«} |jdd D
cgc]#}
2025-10-28 21:09:47 +01:00
t-|
j|
j.¬
«Œ%} }
2025-10-28 20:54:15 +01:00
|j$r3d j1|j$D cgc]} | j.Œc} «nd}
2025-10-28 21:09:47 +01:00
|j"r|j"dd ngDcgc]#}t3|j|j.¬