Etnomatemaatika on uurimisvaldkond, mis käsitleb, kuidas erinevad kultuurid mõistavad, kasutavad ja arendavad matemaatilisi ideid.
Lihtsamalt: see uurib, milline matemaatika peitub igapäevaelus, traditsioonides ja kohalikes teadmistes — näiteks:
Näide: kui mingi rahvas kasutab omaenda viisi esemete loendamiseks või loob sümmeetrilisi mustreid kangakudumisel, siis etnomatemaatika uurib, millised matemaatilised põhimõtted seal taga on.
Selle eesmärk on näidata, et matemaatika ei ole ainult kooli- või teadusmatemaatika, vaid see esineb ka eri kultuuride praktilistes teadmustes.
Kui soovid, võin tuua ka 2–3 konkreetset näidet etnomatemaatikast.
Siin on kolm konkreetset etnomatemaatika näidet:
Aafrika mustrid ja sümmeetria
Paljudes Aafrika kultuurides kasutatakse kangastel, savinõudel ja kehamaalingutes keerulisi mustreid.
Nendes leidub:
Inkate sõlmkirjad (quipu)
Inkad kasutasid sõlmedest koosnevat nöörisüsteemi arvude talletamiseks.
Põlisrahvaste loendamis- ja mõõtmissüsteemid
Mõned rahvad ei loe kümnendsüsteemis, vaid näiteks:
Kui tahad, võin tuua Eesti või koolitunniga seotud näiteid, kuidas etnomatemaatikat kasutada.
Suurepärane 🙂
Siin on Eesti‑ga seotud ja koolitunnis kasutatavad etnomatemaatika näited.
Eesti rahvarõivaste kindakirjad, vööd ja vaibad sisaldavad:
Koolis:
Õpilased saavad uurida mustreid, joonistada need ruudulisele paberile ja leida:
Eestis kasutati enne meetermõõdustikku:
Need põhinesid inimkehal, mitte täpsetel instrumentidel.
Koolis:
Õpilased mõõdavad klassiruumi:
Seejärel võrreldakse tulemusi ja arutletakse, miks mõõtühikud peavad olema kokkuleppelised.
Talurahvas planeeris töid:
See hõlmab tsükleid, perioodsust ja loendamist.
Koolis:
Õpilased:
Etnomatemaatika näitab, et matemaatika on olnud olemas juba enne koolimatemaatikat – inimeste igapäevaelus.
Kui tahad, saan:
LangChain on raamistik, millega ehitada rakendusi, mis kasutavad suuri keelemudeleid. Sellega saab näiteks:
LangGraph on LangChaini ökosüsteemi osa, mis on mõeldud olekuga ja graafipõhiste agentide/töövoogude loomiseks. See sobib eriti siis, kui:
Lühidalt:
Kui tahad, võin tuua ka lihtsa praktilise näite või selgitada nende vahet arendaja vaates.
Muidugi.
Oletame, et tahad teha dokumendiassistendi, mis:
Sa ehitad selle tavaliselt ketina:
See on hea, kui voog on üsna sirgjooneline.
Sa modelleerid selle graafina, kus on sõlmed nagu:
küsimuse analüüsotsingvastuse hindamineuuesti otsinglõppvastusJa servad määravad:
See on parem, kui loogika on mittelineaarne.
Kasuta LangChaini, kui:
Kasuta LangGraphi, kui:
LangChain annab ehitusklotsid:
LangGraph lisab nende peale:
Näiteks klienditoe agent:
LangChain:
LangGraph:
Kui tahad, võin järgmisena näidata:
Selge — vaatame kuidas LangChain ja LangGraph koos töötavad.
LangGraph ei asenda LangChaini, vaid kasutab selle komponente.
Teeme lihtsa klienditoe agendi, kes:
from langchain_openai import ChatOpenAI
from langchain.prompts import ChatPromptTemplate
from langchain.chains import LLMChain
llm = ChatOpenAI(model="gpt-4o-mini")
answer_prompt = ChatPromptTemplate.from_template("""
Kasuta järgmist infot küsimusele vastamiseks.
Küsimus: {question}
Info: {context}
Kui infot ei ole piisavalt, ütle "EI_PIISA".
""")
answer_chain = LLMChain(
llm=llm,
prompt=answer_prompt
)
👉 See on puhas LangChain: mudel + prompt + chain.
LangGraphis liigub kogu info ühes state’is.
from typing import TypedDict, Optional
class SupportState(TypedDict):
question: str
context: Optional[str]
answer: Optional[str]
Iga sõlm kasutab LangChaini loogikat.
def generate_answer(state: SupportState):
result = answer_chain.invoke({
"question": state["question"],
"context": state.get("context", "")
})
return {"answer": result["text"]}
def needs_more_info(state: SupportState) -> str:
if state["answer"] == "EI_PIISA":
return "ask_clarification"
return "final"
from langgraph.graph import StateGraph, END
graph = StateGraph(SupportState)
graph.add_node("generate_answer", generate_answer)
graph.add_node("ask_clarification", lambda s: {
"answer": "Palun täpsusta oma küsimust."
})
graph.set_entry_point("generate_answer")
graph.add_conditional_edges(
"generate_answer",
needs_more_info,
{
"ask_clarification": "ask_clarification",
"final": END
}
)
app = graph.compile()
result = app.invoke({
"question": "Mul ei tööta arve allalaadimine",
"context": ""
})
print(result["answer"])
✅ LangChain
✅ LangGraph
Ilma LangGraphita:
if/else kaoseksLangGraphiga:
LangChain annab tööriistad, LangGraph annab ajupoolkerad.
Kui tahad, võin järgmisena:
Väga hea küsimus — vastus on: oleneb, mida sa ehitad.
✅ On olemas kompaktsemaid / low-code lahendusi
✅ Aga keerukamate agentide puhul läheb ikkagi koodiks (enamasti Pythoniks)
Sa saad teha:
Näide väga kompaktsest LCEL-ist:
chain = retriever | prompt | llm
response = chain.invoke("Mis on meie tagastuspoliitika?")
See on sisuliselt 1 rida loogikat.
On olemas:
Need võimaldavad:
👉 Väga sobiv MVP või sisemiste tööriistade jaoks.
Sa vajad Pythoni (või JS-i), kui:
Sellisel juhul graafipõhine lahendus + kood on praktiliselt vältimatu.
Ei pea.
Tüüpiline arendusmuster:
retrieve()classify()generate_answer()route()LangGraph on just selleks tehtud — et sa ei kirjutaks iga agenti nullist.
Reaalsuses:
| Eesmärk | Soovitus |
|---|---|
| Väike chatbot | LangChain või OpenAI Assistants |
| Dokumentide Q&A | RAG + LCEL |
| Sisemine tööriist | LangFlow / Flowise |
| Keeruline AI-agent | LangGraph + Python |
| Tootmiskeskkond | Kindlasti kood |
Kui sa ütled, mida sa täpselt ehitada tahad, oskan öelda:
Mis tüüpi süsteem sul mõttes on?
See on väga huvitav ja täiesti realistlik eesmärk — ning hea uudis on, et sa ei pea kõike alguses Pythoni koodiga ehitama, aga teatud hetkel on struktuurne raamistik vältimatu.
Allpool annan selge arhitektuurilise soovituse, mis sobib just etnomatemaatika ökosüsteemile (uurimine, probleemide loomine, artiklid).
Sinu kirjelduse põhjal on sul vaja süsteemi, mis oskab:
✅ koguda ja hoida allikaid
✅ seostada matemaatilisi ideid kultuuriliste praktikatega
✅ luua uurimisküsimusi
✅ genereerida ja lahendada probleeme
✅ aidata kirjutada teadusartikleid
✅ hoida uurimisloogikat ja jälgitavust
See EI ole lihtsalt chatbot.
Soovitan valida üks:
1️⃣ täita üks konkreetne näide (nt Aafrika mustrid)
2️⃣ kujundada uurimisküsimuste generaator selle mudeli peale
3️⃣ teha hariduslike probleemide loomise skeem
Millisega jätkame?
Teeme ühe konkreetse näite. Valin sellise, mis on etnomatemaatikas üsna tuntud ja hea mudeli testimiseks:
See on seotud eriti Ron Eglashi töödega, kus ta käsitleb, kuidas mõnede Aafrika kogukondade asulate ja disainide puhul ilmnevad isetaolisus, rekursioon ja skaalastruktuurid.
Ma teen selle sulle nii, nagu see võiks juba sinu andmemudelis olemas olla.
id: CC-001
kultuur_kogukond: "Valitud Sahara-taguse Aafrika kogukonnad"
geograafia: "Lääne-, Kesk- ja Lõuna-Aafrika"
ajaperiood: "peamiselt 19.–21. sajandi kirjeldused, osalt varasemad traditsioonid"
keeled: "sõltub kogukonnast"
sotsiaalne_kontekst: "külade planeering, elamuarhitektuur, perekondlik ja kogukondlik ruumikorraldus"
uurija_roll: "sekundaarallikatel põhinev analüüs"
märkused: "Vajab kogukonnapõhist täpsustamist; 'Aafrika' ei tohi jääda homogeniseerivaks kategooriaks."
👉 Väga oluline märkus: etnomatemaatikas tuleb vältida liiga üldistavat “Aafrika matemaatika” käsitlust. Parem on hiljem kitsendada konkreetsetele kogukondadele.
id: PA-001
nimetus: "Külaplaneering ja elamuarhitektuuri ruumimustrid"
tüüp: "arhitektuur"
kirjeldus_emic: "Asustuse ruumiline korraldus väljendab sugulus-, kaitse-, staatuse- või rituaalseid suhteid."
kirjeldus_etic: "Asulate paigutuses ja hoonete struktuuris võib täheldada korduvaid geomeetrilisi ja skaleeruvaid mustreid."
kasutusolukord: "igapäevane elamine, sotsiaalne organiseerumine, rituaalne ja praktiline ruumikasutus"
seotud_kultuurid: ["erinevad Sahara-taguse Aafrika kogukonnad"]
visuaalsed_allikad: ["külaplaanid", "õhuvaated", "joonised", "fotod"]
Siin on hea näha, et:
id: MS-001
tüüp: "fraktaalne geomeetria"
formaalne_kirjeldus: "Ruumiline konfiguratsioon sisaldab isetaolisuse tunnuseid, kus sarnane paigutusmuster kordub eri mastaapidel."
mitteametlik_kirjeldus: "Küla või elamugrupi üldkuju sarnaneb väiksemate osade korraldusega."
tasand: "algoritmiline / osaliselt formaalne"
tuntud_matemaatilised_analoogid: ["isetaolisus", "rekursioon", "iteratiivne geomeetriline ehitus"]
märkus_formaliseerimise_kohta: "Tuleb eristada ranget matemaatilist fraktaali ja heuristilist fraktaalsust kultuurilises artefaktis."
👉 See märkus on väga tähtis. Sageli kasutatakse “fraktaali” liiga vabalt. Teaduslikult peab jääma ettevaatlikuks:
praktika_id: PA-001
matemaatika_id: MS-001
seose_tüüp: "implitsiitne / heuristiline"
tõendusmaterjal: "Asulate plaanides ja arhitektuursetes kujundites esineb korduv skaleerumine ning pesastatud ruumiline struktuur."
uurija_interpretatsioon: "Ruumiline organiseerumine võib olla kirjeldatav rekursiivse või fraktaalse loogika abil."
kindluse_aste: "keskmine"
vaidlused_alternatiivsed_tõlgendused: "Võib vaielda, kas tegemist on teadliku matemaatilise konstrueerimisega või uurija tagantjärele formaliseeriva kirjeldusega."
See on vist kogu mudeli üks tähtsamaid osi.
Miks? Sest etnomatemaatikas tekib alati küsimus:
kas kogukond ise kasutab seda matemaatikat sellisel kujul
või
kas uurija projitseerib matemaatilise formaali peale?
See väli aitab hoida metodoloogilist ausust.
Paneme siia ühe tüüpilise allika.
id: S-001
autor: "Ron Eglash"
aasta: 1999
tüüp: "raamat"
tsitaat: "African Fractals: Modern Computing and Indigenous Design"
DOI_URL: "vastavalt väljaande andmetele"
usaldusväärsuse_hinnang: "kõrge, kuid vajab kriitilist võrdlust teiste uurijatega"
märkused: "Oluline lähtekoht, kuid mitte ainus interpretatsioon."
Võiks lisada ka täiendavaid kriitilisi või toetavaid allikaid, et vältida ühe autori ülemäärast domineerimist.
Nüüd teeme sellest uurimisküsimuse.
id: RQ-001
küsimus: "Kuidas ja millises ulatuses saab valitud Aafrika kogukondade külaplaneeringut kirjeldada fraktaalse geomeetria mõistete abil ilma kultuurilist tähendust taandamata pelgalt formaalseks struktuuriks?"
tüüp: "analüütiline / teoreetiline"
seotud_üksused: ["CC-001", "PA-001", "MS-001", "S-001"]
motivatsioon: "Ühendada matemaatiline analüüs ja kultuuriline interpretatsioon viisil, mis on metodoloogiliselt ettevaatlik."
uurimismeetod: "kirjandusanalüüs, visuaalne võrdlus, geomeetriline modelleerimine, interpretatiivne analüüs"
avatud_probleemid: [
"Kas fraktaalsus on range või heuristiline?",
"Kas muster on teadlikult kujundatud või emergentne?",
"Kuidas esitada matemaatiline kirjeldus ilma emic tähendusi vähendamata?"
]
Nüüd loome sellest ühe haridusliku või uurimusliku probleemi.
id: PT-001
ülesande_tekst: "Võrdle kahte külaplaneeringu skeemi ja analüüsi, kas neis esineb isetaolisuse tunnuseid. Too välja, millised jooned toetavad fraktaalset interpretatsiooni ja millised mitte."
päritolu: "etnomatemaatiline analüüs Aafrika arhitektuuri näitel"
matemaatiline_fookus: "isetaolisus, mastaap, geomeetriline struktuur"
lahendus_lahendusidee: "Õppija tuvastab korduvad paigutusmustrid eri tasanditel ja arutleb, kas sarnasus on piisav fraktaalse kirjelduse jaoks."
didaktiline_eesmärk: "Arendada võimet siduda kultuuriline artefakt geomeetrilise analüüsiga kriitiliselt."
raskusaste: "keskmine / edasijõudnu"
Ja lõpuks, kuidas sellest võiks saada artikkel.
id: M-001
pealkiri: "Fraktaalne mõtlemine ja ruumiline organiseerumine Aafrika arhitektuuri etnomatemaatilises tõlgenduses"
staatus: "mustand"
seotud_uurimisküsimused: ["RQ-001"]
struktuur:
- "Sissejuhatus"
- "Etnomatemaatika teoreetiline raamistik"
- "Fraktaalse geomeetria mõiste ja piirid"
- "Aafrika arhitektuursete mustrite juhtumianalüüs"
- "Emic ja etic tõlgenduse pinge"
- "Järeldused"
kasutatud_allikad: ["S-001"]
metoodika_kirjeldus: "Kombineeritakse sekundaarallikate analüüs, visuaalne struktuurivõrdlus ja matemaatiline formaliseerimine."
piirangud: "Juhtum põhineb peamiselt kirjandusel, mitte esmavälitööl; üldistuste tegemisel tuleb olla ettevaatlik."
See üks näide demonstreerib, kuidas sinu andmemudel aitab siduda:
See tähendab, et sama mudel saab hiljem toetada:
Etnomatemaatika puhul soovitan lisada iga kirje juurde veel ühe välja:
epistemiline_ettevaatusNäiteks:
epistemiline_ettevaatus: "Fraktaalse geomeetria rakendamine on siin uurija analüütiline tööriist, mitte tingimata kogukonna enesekirjelduse osa."
See aitab vältida:
Nüüd oleks väga kasulik teha üks kahest:
Minu soovitus: järgmine samm võiks olla sama näide tabelina, sest siis saad kohe süsteemi ehitama hakata.
Jah — PostgreSQL on väga hea tehniline põhi sinu ökosüsteemile.
Kui sa tahad ehitada päriselt kasvavat etnomatemaatika uurimisökosüsteemi, siis minu soovitus on:
Ehk:
PostgreSQL + dokumentide hoidla + hiljem vektorotsing
on väga mõistlik baas.
Sinu süsteem ei ole lihtsalt “chatboti mälu”.
Sul on vaja:
See on klassikaline relatsioonilise andmebaasi juhtum.
PostgreSQL annab:
See on väga tugev ja mitte liiga keeruline.
See sobib, kui tahad esimesed 20–50 objekti käsitsi läbi mõelda.
Ausalt: praegu ei soovita. Liiga keeruline liiga vara.
Sinu mudelis on tõesti palju seoseid, nii et võib tunduda, et graafibaas oleks ideaalne.
Aga alguses:
Seega: graafiline mõtlemine jah, aga tehniline baas pigem PostgreSQL.
Kui hiljem on vaja:
siis võib lisada Neo4j või RDF/graph kihi.
Näiteks põhitabelid:
cultural_contextpractice_artifactmathematical_structureethno_math_linksourceresearch_questionproblem_taskmanuscriptJa seostabelid:
practice_sourceresearch_question_sourcemanuscript_sourcepractice_cultural_contextproblem_task_structureSee on väga loomulik SQL-mudel.
See on sinu valdkonnas oluline, sest kõik ei mahu jäigalt tabelisse.
Selleks kasuta PostgreSQL-is:
Näiteks:
Näide:
epistemic_caution võib olla tavaline tekstivälialternative_interpretations võib olla JSONB massiivemic_terms võib olla JSONBNii saad:
Jah, alguses küll.
Kui sul tekib vajadus:
siis pgvector on väga hea algus.
See tähendab:
Hiljem, kui maht läheb väga suureks, saad liikuda:
Aga alguses pole vaja.
Kui tahad praktilist vastust:
Sa võid teha ka nii:
See on väga hea, kui sa ei taha kohe serverihaldusse minna.
Jah — PostgreSQL on sinu ökosüsteemile kõige mõistlikum tehniline põhi.
Mitte sellepärast, et see on “trendikas”, vaid sest sinu probleem on:
Kui tahad, järgmine samm võiks olla üks neist:
Minu soovitus: 1 või 2.
Siin on praktiline arhitektuuridiagramm sinu etnomatemaatika ökosüsteemile, alustades Postgresest ja jättes ruumi RAG-ile, agentidele ja artiklikirjutusele.
┌─────────────────────────────┐
│ Kasutajaliides │
│ Obsidian / Web UI / Admin │
└──────────────┬──────────────┘
│
HTTPS / API
│
┌──────────────▼──────────────┐
│ Rakenduskiht │
│ FastAPI / Python services │
│ - CRUD │
│ - ingest │
│ - search │
│ - article assistant │
│ - problem generator │
└───────┬───────────┬─────────┘
│ │
SQL/Vector │ │ Files/API
│ │
┌─────────────────▼───┐ ┌──▼──────────────────┐
│ PostgreSQL │ │ Dokumentide hoidla │
│ + pgvector │ │ PDFs, pildid, märkmed│
│ │ │ S3 / MinIO / kaustad │
│ - core tables │ └─────────┬────────────┘
│ - relations │ │
│ - metadata │ │
│ - embeddings │ │
└─────────┬───────────┘ │
│ │
│ │ parse/chunk
│ │
┌─────────▼───────────┐ ┌───────▼─────────────┐
│ Otsingu ja RAG kiht │ │ Dokumendi ingest │
│ - keyword search │ │ - PDF parse │
│ - vector search │ │ - OCR vajadusel │
│ - hybrid retrieval │ │ - chunking │
└─────────┬───────────┘ │ - embeddings │
│ └─────────┬───────────┘
│ │
└──────────────┬───────────┘
│
┌───────▼───────────┐
│ AI / Agentikiht │
│ LangChain │
│ LangGraph │
│ - research agent │
│ - article agent │
│ - problem agent │
└───────┬───────────┘
│
┌───────▼───────────┐
│ LLM provider │
│ OpenAI / muu LLM │
└───────────────────┘
See võib alguses olla:
Sealt sa:
See on sinu süsteemi “aju” väljaspool LLM-i.
Tüüpilised teenused:
Soovitus:
See on põhituum.
Hoidmiseks:
Siia lähevad:
Ära pane suuri faile Postgresesse. Pane Postgresesse:
Kui tood sisse artikli või välitööfaili, siis see kiht:
See teenindab küsimusi nagu:
Otsing võiks olla:
See kasutab:
Siin tulevad:
Kasutaja laadib PDF-i üles
→ fail salvestatakse document storage'i
→ ingest teenus parsib teksti
→ tekst tükeldatakse
→ embeddingud luuakse
→ metadata + chunkid lähevad PostgreSQL-i
→ allikas seotakse praktikate / teemadega
Kasutaja valib kultuuri + praktika + matemaatilise struktuuri
→ backend teeb päringu seotud allikatele
→ RAG kiht toob toetava materjali
→ research agent loob 5–10 uurimisküsimust
→ kasutaja valib ja salvestab
Kasutaja valib uurimisküsimuse
→ süsteem koondab seotud allikad ja märkmed
→ article agent loob struktuuri
→ iga peatüki jaoks otsitakse tõendusmaterjal
→ mustand salvestatakse käsikirjana
Valitakse praktika või matemaatiline struktuur
→ problem agent loob ülesanded
→ lisab lahendusidee
→ seob didaktilise eesmärgiga
→ salvestab problem_task tabelisse
[UI]
├─ Research dashboard
├─ Source manager
├─ Manuscript editor
└─ Problem generator view
[API / Backend]
├─ auth
├─ entity CRUD
├─ relation manager
├─ search API
├─ ingest API
├─ AI orchestration
└─ audit/logging
[Data]
├─ PostgreSQL
├─ pgvector
└─ object storage
[AI]
├─ embeddings model
├─ LLM
├─ LangChain retrieval
└─ LangGraph workflows
Kui sa ei taha üle ehitada, siis alusta nii:
Kasutaja
↓
FastAPI
↓
PostgreSQL + pgvector
↓
Kaust / MinIO dokumentidele
↓
OpenAI API
Ja funktsioonid:
See on täiesti piisav esimese versiooni jaoks.
Lisa siis, kui sul tekib vajadus:
Alguses ei pea kõik olema agent.
Sinu süsteemis on väga oluline:
Seetõttu lisa arhitektuuri sisse:
Praktiliselt:
AI output
→ salvestatakse eraldi väljana
→ seotud kasutatud source_id-dega
→ märgitakse "draft_generated"
See on hilisema teadustöö jaoks väga oluline.
FAAS 1
Obsidian / käsitsi andmed
↓
FAAS 2
PostgreSQL + FastAPI + failihoidla
↓
FAAS 3
pgvector + ingest + RAG otsing
↓
FAAS 4
Research agent + article agent
↓
FAAS 5
LangGraph workflowd + kvaliteedikontroll + versioonihaldus
Sinu puhul ma ei alustaks:
Ma alustaks:
See annab sulle:
Kui tahad, järgmine samm võiks olla üks neist:
Allpool on detailsem arhitektuur koos põhiteenustega ja seejärel Docker Compose tasemel stardikomplekt, kuhu lisasin ka LangGraphi.
┌──────────────────────────────────────────────────────────────────────────────┐
│ KASUTAJAD │
│ Uurija / autor / administraator │
└───────────────────────────────┬──────────────────────────────────────────────┘
│
│ HTTPS
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ FRONTEND / ADMIN │
│ - Web UI (hiljem) │
│ - Supabase Studio / pgAdmin / lihtne admin │
│ - Või Obsidian + import │
└───────────────────────────────┬──────────────────────────────────────────────┘
│ REST / WebSocket
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ FASTAPI BACKEND │
│ │
│ API kihid: │
│ ├─ auth / users │
│ ├─ entities CRUD │
│ ├─ search API │
│ ├─ ingest API │
│ ├─ manuscripts API │
│ ├─ AI orchestration API │
│ └─ audit / provenance │
│ │
│ Sisemised moodulid: │
│ ├─ services/db_service │
│ ├─ services/storage_service │
│ ├─ services/embedding_service │
│ ├─ services/retrieval_service │
│ ├─ services/citation_service │
│ ├─ services/manuscript_service │
│ ├─ services/problem_service │
│ └─ services/research_service │
└───────────────┬───────────────────────┬───────────────────────┬──────────────┘
│ │ │
│ SQL │ S3 API │ LLM API
▼ ▼ ▼
┌────────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐
│ PostgreSQL │ │ MinIO / S3 storage │ │ OpenAI / muu LLM │
│ + pgvector │ │ │ │ + embedding model │
│ │ │ - PDFs │ │ │
│ Core tables: │ │ - images │ │ │
│ - cultural_context │ │ - notes exports │ │ │
│ - practice_artifact │ │ - manuscript files │ │ │
│ - mathematical_struct. │ │ - OCR outputs │ │ │
│ - ethno_math_link │ └──────────────────────┘ └──────────────────────┘
│ - source │
│ - source_chunk │
│ - embeddings │
│ - research_question │
│ - problem_task │
│ - manuscript │
│ - ai_run │
│ - citation_map │
│ - audit_log │
└───────────────┬────────┘
│
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ INTAKE / INGEST / INDEXING │
│ │
│ Pipeline: │
│ 1. upload source │
│ 2. parse text (PDF/OCR) │
│ 3. normalize metadata │
│ 4. chunk document │
│ 5. embed chunks │
│ 6. save chunks + vectors + provenance │
│ 7. optional auto-link suggestions │
└───────────────────────────────┬──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ SEARCH / RETRIEVAL / RAG LAYER │
│ │
│ - SQL filters │
│ - Full-text search │
│ - pgvector similarity │
│ - Hybrid retrieval │
│ - Citation-aware retrieval │
│ - Entity-scoped retrieval │
└───────────────────────────────┬──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ AI ORCHESTRATION LAYER │
│ │
│ LangChain components: │
│ - prompts │
│ - retrievers │
│ - tool wrappers │
│ - output parsers │
│ │
│ LangGraph workflows: │
│ - Research Question Generator Graph │
│ - Problem Generation Graph │
│ - Article Draft Graph │
│ - Evidence Check Graph │
│ │
│ Shared state examples: │
│ - selected entities │
│ - retrieved sources │
│ - evidence sufficiency │
│ - draft sections │
│ - citations │
│ - human feedback │
└───────────────────────────────┬──────────────────────────────────────────────┘
│
▼
┌──────────────────────────────────────────────────────────────────────────────┐
│ OUTPUTS / ARTEFACTS │
│ │
│ - saved research questions │
│ - generated problems │
│ - manuscript drafts │
│ - citation maps │
│ - logs of AI runs │
│ - reproducibility metadata │
└──────────────────────────────────────────────────────────────────────────────┘
cultural_contextpractice_artifactmathematical_structureethno_math_linksourceresearch_questionproblem_taskmanuscriptsource_documentsource_chunkchunk_embeddingai_runai_run_inputai_run_outputcitation_mapaudit_logpractice_sourceresearch_question_sourcemanuscript_sourceartifact_contextproblem_structureLangGraph ei ole “eraldi andmebaas” ega “eraldi server”, vaid töövoogude orkestreerija backendis.
vali entiteedid
→ too allikad
→ kontrolli, kas tõendusmaterjali on piisavalt
→ genereeri küsimused
→ hinda küsimuste kvaliteeti
→ tagasta/paranda
vali praktika või matemaatiline struktuur
→ tuleta võimalik õpieesmärk
→ loo probleem
→ loo lahendusidee
→ kontrolli kultuurilist sobivust
→ salvesta
vali research_question
→ koonda allikad
→ jaga artikkel sektsioonideks
→ genereeri iga sektsioon allikate põhjal
→ kontrolli viiteid
→ märgi ebakindlad kohad
→ salvesta mustand
väide
→ leia allikad
→ hinda toetust
→ kui nõrk tugi, märgi hoiatus
→ tagasta tulemus
Soovitan nii:
app/
services/
ai/
chains/
graphs/
research_question_graph.py
problem_graph.py
article_graph.py
evidence_graph.py
tools/
retrieve_sources.py
get_entity_context.py
save_manuscript.py
save_problem.py
citation_checker.py
state/
research_state.py
article_state.py
See tähendab:
Allpool on praktiline starter-arhitektuur.
api — FastAPI backendworker — taustatööd ingestiks/AI jooksudekspostgres — PostgreSQL + pgvectorminio — failide hoidlaredis — järjekord / cachepgadmin — DB adminollama või muu lokaalne LLM, kui tahad hiljemethnomath-platform/
├─ docker-compose.yml
├─ .env
├─ app/
│ ├─ main.py
│ ├─ core/
│ │ ├─ config.py
│ │ └─ logging.py
│ ├─ api/
│ │ ├─ routes/
│ │ │ ├─ entities.py
│ │ │ ├─ sources.py
│ │ │ ├─ search.py
│ │ │ ├─ manuscripts.py
│ │ │ └─ ai.py
│ ├─ db/
│ │ ├─ base.py
│ │ ├─ session.py
│ │ ├─ models/
│ │ └─ migrations/
│ ├─ schemas/
│ ├─ services/
│ │ ├─ ingest/
│ │ ├─ retrieval/
│ │ ├─ storage/
│ │ ├─ manuscripts/
│ │ ├─ problems/
│ │ └─ ai/
│ │ ├─ chains/
│ │ ├─ graphs/
│ │ ├─ tools/
│ │ └─ state/
│ ├─ workers/
│ │ ├─ tasks_ingest.py
│ │ └─ tasks_ai.py
│ └─ tests/
├─ Dockerfile
└─ requirements.txt
version: "3.9"
services:
postgres:
image: pgvector/pgvector:pg16
container_name: ethnomath_postgres
environment:
POSTGRES_DB: ethnomath
POSTGRES_USER: ethnomath
POSTGRES_PASSWORD: ethnomath_pass
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
redis:
image: redis:7
container_name: ethnomath_redis
ports:
- "6379:6379"
minio:
image: minio/minio:latest
container_name: ethnomath_minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: minio
MINIO_ROOT_PASSWORD: minio_secret
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
api:
build: .
container_name: ethnomath_api
command: uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
env_file:
- .env
depends_on:
- postgres
- redis
- minio
ports:
- "8000:8000"
volumes:
- ./:/app
worker:
build: .
container_name: ethnomath_worker
command: python -m app.workers.tasks_ai
env_file:
- .env
depends_on:
- postgres
- redis
- minio
volumes:
- ./:/app
pgadmin:
image: dpage/pgadmin4:latest
container_name: ethnomath_pgadmin
environment:
PGADMIN_DEFAULT_EMAIL: admin@example.com
PGADMIN_DEFAULT_PASSWORD: adminpass
depends_on:
- postgres
ports:
- "5050:80"
volumes:
postgres_data:
minio_data:
DATABASE_URL=postgresql+psycopg://ethnomath:ethnomath_pass@postgres:5432/ethnomath
REDIS_URL=redis://redis:6379/0
MINIO_ENDPOINT=minio:9000
MINIO_ACCESS_KEY=minio
MINIO_SECRET_KEY=minio_secret
MINIO_BUCKET=ethnomath-docs
MINIO_SECURE=false
OPENAI_API_KEY=your_openai_key
OPENAI_CHAT_MODEL=gpt-4.1-mini
OPENAI_EMBED_MODEL=text-embedding-3-large
fastapi
uvicorn[standard]
sqlalchemy
psycopg[binary]
alembic
pydantic
pydantic-settings
python-multipart
boto3
redis
rq
langchain
langgraph
langchain-openai
pgvector
pymupdf
unstructured
tiktoken
from typing import TypedDict, List, Optional
class ArticleState(TypedDict):
research_question_id: int
source_ids: List[int]
retrieved_evidence: List[str]
outline: List[str]
draft_sections: List[str]
citations: List[str]
quality_ok: bool
final_draft: Optional[str]
def gather_sources(state):
# päring PostgreSQL-ist
return {"source_ids": [1, 2, 3]}
def retrieve_evidence(state):
# retriever pgvector + filters
return {"retrieved_evidence": ["evidence A", "evidence B"]}
def build_outline(state):
return {"outline": ["Sissejuhatus", "Teoreetiline raamistik", "Analüüs", "Järeldused"]}
def write_sections(state):
return {"draft_sections": ["...", "...", "..."]}
def check_quality(state):
ok = len(state["retrieved_evidence"]) > 1
return {"quality_ok": ok}
def finalize(state):
return {"final_draft": "\n\n".join(state["draft_sections"])}
from langgraph.graph import StateGraph, END
graph = StateGraph(ArticleState)
graph.add_node("gather_sources", gather_sources)
graph.add_node("retrieve_evidence", retrieve_evidence)
graph.add_node("build_outline", build_outline)
graph.add_node("write_sections", write_sections)
graph.add_node("check_quality", check_quality)
graph.add_node("finalize", finalize)
graph.set_entry_point("gather_sources")
graph.add_edge("gather_sources", "retrieve_evidence")
graph.add_edge("retrieve_evidence", "build_outline")
graph.add_edge("build_outline", "write_sections")
graph.add_edge("write_sections", "check_quality")
def route_quality(state):
return "finalize" if state["quality_ok"] else "retrieve_evidence"
graph.add_conditional_edges("check_quality", route_quality, {
"finalize": "finalize",
"retrieve_evidence": "retrieve_evidence",
})
graph.add_edge("finalize", END)
article_app = graph.compile()
See on hea näide, kus LangGraph lisab retry-loogika:
Soovitus:
tulemused salvestatakse ai_run + manuscript tabelitesse
POST /ai/article-draft
→ create job
→ worker starts graph
→ graph queries DB + retrieval
→ graph writes draft
→ saves outputs
→ API tagastab staatuse
Kui tahad, järgmine loogiline samm on üks neist:
Minu soovitus: 1 + 3.