Artificial intelligence / Software & Backend / Data science
TenderAI
A Streamlit prototype combining Turkish tender PDF extraction, AI-assisted risk review, retrieval-based questions, comparison and reporting components.
Prototype
Python
Streamlit
OpenAI
Gemini
FAISS
SQLAlchemy
Docker
Original code-generated category illustration; not a product screenshot.
Overview
TenderAI explores structured review of lengthy tender specifications through a Streamlit application. It includes PDF text extraction, OpenAI/Gemini adapters, FAISS retrieval, company matching and document comparison. SQLAlchemy stores analysis records, and reporting modules provide multiple export formats. Findings are review drafts rather than authoritative decisions: source passages and calculations require human inspection, and the prototype is not a verified procurement or legal service.
Problem and objectives
Tender specifications contain numerous conditions, dates, eligibility requirements and cross-references. Comparing documents or answering a specific question can require repeatedly reading the same passages. An automated summary may omit an important requirement when disconnected from its source. Document context, company information and review outputs therefore need to be considered together, with a clear path back to the original material.
My role
Software development of document analysis, retrieval and user-interface components.
Solution approach
The application extracts PDF text and passes it into analysis components using OpenAI or Gemini adapters according to the chosen flow. A FAISS retrieval layer brings document chunks into question-answering. Company matching and comparison modules bring different review tasks into the same interface. SQLAlchemy persists users and analysis records, while PDF, Excel and DOCX report components export results. A synthetic demo mode allows interface exploration without real documents or provider credentials.
Implementation details
01
Retrieval shaped around tender documents
IhaleAnalizAI defaults to 1,500-character chunks with 200-character overlap. Its RecursiveCharacterTextSplitter tries tender headings such as Madde, BÖLÜM and Ek before generic whitespace separators. OpenAI embeddings create an in-memory FAISS index; each analysis question retrieves nearby chunks for its prompt. Overlap can carry context across a split clause, but similarity search cannot establish that every requirement was found. This is a question-focused analysis path rather than a single undifferentiated document summary.
02
Six review steps and structured aggregation
The main analysis pipeline runs risk, required documents, penalties, financial summary and timeline sequentially. Its executive summary then receives those earlier results as context. Sequential execution makes rate-limit concerns explicit, while retaining accumulated request latency. The response parser tries plain JSON, fenced JSON and trailing-comma cleanup; unresolved responses retain raw_response and parse_error fields. This exposes formatting failures rather than silently discarding them, but successful parsing does not establish that a generated interpretation is correct.
03
Analysis retrieval and chat use different context paths
The chatbot is separate from the main FAISS analysis path. It retains a bounded document context and sends the first 20,000 characters plus the last five conversation messages to Gemini. Consequently, not every question-answer flow should be described as the same retrieval architecture. Without a usable key it follows a demo path; quota or service failures can return a labeled demo fallback. This enables interface exploration while making clear that information near the end of a long document may be absent from chatbot context.
Architecture flow
01
Streamlit interface → PDF upload / text extraction
02
Analysis orchestration → OpenAI / Gemini adapters
03
Document chunks → FAISS retrieval → questions and answers
04
SQLAlchemy → user and analysis records
05
Comparison / company matching → report exports
Conceptual flow derived from project descriptions; not an application screenshot.
Core components
Tender PDF text extraction
AI-assisted risk-review flow
FAISS document question-answering
Company matching and tender comparison
PDF / Excel / DOCX report components
Synthetic demonstration mode
Technical challenges
Extracting consistent text from varied PDF layouts.
Keeping generated assessments connected to document context.
Separating first-use tokenizer downloads from offline test requirements.
Engineering decisions
The application uses Streamlit and Python components rather than a standalone REST server.
Retrieval and model-provider integrations remain separate modules.
Synthetic demonstrations are distinct from live-provider configuration.
Testing and validation
Historical validation of open PR #1 passed 234 tests with tokenizer tables cached and external network sockets blocked.
An uncached offline run failed on first-use tokenizer downloads; Docker runtime and live-model quality were not validated.
Outcomes
Extraction, retrieval and reporting components are combined in one application.
Question-answering, comparison and company matching have separate Python modules.
Limitations and current status
Text extraction from image-only scanned PDFs is not guaranteed.
Generated analysis can omit or misinterpret important conditions.
Live providers can transmit document text to external services.
CI/lint and documentation corrections remain in unmerged PR #1, not a released update.
The technical account also draws on documentation in the open improvement PR. This does not imply that the PR has been merged or the product released.