Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,15 @@ grpcui: ## Open gRPC UI in browser
@echo "Opening gRPC UI at http://localhost:8081"
@open http://localhost:8081 2>/dev/null || xdg-open http://localhost:8081 2>/dev/null || echo "Open http://localhost:8081 in your browser"

db: ## Open SQLite Web browser
@echo "Opening SQLite Web at http://localhost:8082"
@open http://localhost:8082 2>/dev/null || xdg-open http://localhost:8082 2>/dev/null || echo "Open http://localhost:8082 in your browser"
db: ## Open pgAdmin web interface (starts with --profile tools if needed)
@if ! docker ps --format '{{.Names}}' | grep -q fi-pgadmin; then \
echo "Starting pgAdmin..."; \
docker-compose --profile tools up -d pgadmin; \
sleep 2; \
fi
@echo "Opening pgAdmin at http://localhost:5050"
@echo "Login: admin@fiapply.local / admin"
@open http://localhost:5050 2>/dev/null || xdg-open http://localhost:5050 2>/dev/null || echo "Open http://localhost:5050 in your browser"

# Status
status: ## Show status of all services
Expand Down Expand Up @@ -92,5 +98,12 @@ quickstart: install build up ## Install, build, and start everything
@echo "Frontend: http://localhost:3000"
@echo "Swagger UI: http://localhost:8080"
@echo "gRPC UI: http://localhost:8081"
@echo "DB Browser: http://localhost:8082"
@echo "pgAdmin: http://localhost:5050"
@echo ""

PYTHONPATH := $(shell pwd)

# Run pytest on the RAG engine tests
test-rag:
@echo "🧪 Running RAG engine tests..."
PYTHONPATH=$(PYTHONPATH) pytest -s -v --full-trace backend/services/rag_engine/tests/test.py
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ FiApply/
├── backend/ # Python gRPC microservices
├── frontend/ # React TypeScript PWA
├── proto/ # Protocol Buffer definitions
├── db/ # SQLite database
├── db/ # PostgreSQL database
└── docs/ # Documentation
```

Expand All @@ -25,7 +25,7 @@ FiApply/
**Tech Stack:**
- **Backend**: Python 3.11+, gRPC, Connect RPC, Playwright, LangChain, LangGraph
- **Frontend**: React 18, TypeScript, Vite, ShadCN UI, Redux Toolkit, Connect-Web
- **Database**: SQLite with vector extensions
- **Database**: PostgreSQL 17-alpine3.22 with pgvector, pg_trgm, pg_stat_statements
- **AI**: Stagehand (browser automation), Ollama/OpenRouter (LLMs)

---
Expand Down Expand Up @@ -63,7 +63,7 @@ python backend/services/llm_manager/example_client.py
- 🎨 **Frontend**: http://localhost:3000
- 📚 **API Docs**: http://localhost:8080 (Swagger UI)
- 🔧 **gRPC Testing**: http://localhost:8081 (gRPC UI)
- 💾 **Database**: http://localhost:8082 (SQLite Web)
- 💾 **Database**: http://localhost:5050 (pgAdmin)

See **[docs/DOCKER.md](docs/DOCKER.md)** for detailed Docker documentation.

Expand Down Expand Up @@ -285,16 +285,17 @@ All tools run automatically with Docker.

| Service | Port | Description |
|---------|------|-------------|
| **postgres** | 5432 | PostgreSQL database |
| **pgadmin** | 5050 | Database management UI |
| **ollama** | 11434 | Local LLM runtime |
| **swagger-ui** | 8080 | API documentation |
| **grpcui** | 8081 | Interactive gRPC testing |
| **sqlite-web** | 8082 | Database browser |

Access via:
```zsh
make swagger # http://localhost:8080
make grpcui # http://localhost:8081
make db # http://localhost:8082
make db # http://localhost:5050 (pgAdmin)
```

---
Expand Down Expand Up @@ -325,7 +326,7 @@ FiApply/
│ ├── ai_orchestrator.proto
│ ├── rag_engine.proto
│ └── llm_manager.proto
├── db/ # SQLite database
├── db/ # PostgreSQL database
├── docs/ # Documentation
├── docker-compose.yml # Full stack orchestration
├── Makefile # Development commands
Expand Down Expand Up @@ -390,7 +391,11 @@ STAGEHAND_API_KEY=...
OPENROUTER_API_KEY=...

# Database
DB_PATH=/path/to/production.db
DB_HOST=postgres
DB_PORT=5432
DB_NAME=fiapply
DB_USER=fiapply_user
DB_PASSWORD=fiapply_password

# Service ports (optional)
GATEWAY_PORT=50051
Expand Down Expand Up @@ -457,8 +462,8 @@ docker-compose exec ai-orchestrator playwright install chromium
- ✅ OpenAPI/Swagger documentation
- ✅ Browser automation with Stagehand
- ✅ Connect RPC (gRPC + HTTP/JSON support)
- ✅ PostgreSQL database with vector search (pgvector)
- ⏳ Service implementations (see TODO comments in code)
- ⏳ Database schema and migrations
- ⏳ Authentication system
- ⏳ Production deployment configs

Expand Down
2 changes: 1 addition & 1 deletion backend/generated/ai_orchestrator_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/generated/ai_orchestrator_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

from backend.generated import ai_orchestrator_pb2 as ai__orchestrator__pb2
import ai_orchestrator_pb2 as ai__orchestrator__pb2


class AIOrchestratorStub(object):
Expand Down
4 changes: 2 additions & 2 deletions backend/generated/api_gateway_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions backend/generated/api_gateway_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

from backend.generated import api_gateway_pb2 as api__gateway__pb2
import api_gateway_pb2 as api__gateway__pb2
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2
from backend.generated import headless_streaming_pb2 as headless__streaming__pb2
import headless_streaming_pb2 as headless__streaming__pb2


class GatewayStub(object):
Expand Down
2 changes: 1 addition & 1 deletion backend/generated/llm_manager_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion backend/generated/llm_manager_pb2_grpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

from backend.generated import llm_manager_pb2 as llm__manager__pb2
import llm_manager_pb2 as llm__manager__pb2


class LLMManagerStub(object):
Expand Down
20 changes: 17 additions & 3 deletions backend/generated/rag_engine_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions backend/generated/rag_engine_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,65 @@ class SearchResult(_message.Message):
score: float
metadata: _struct_pb2.Struct
def __init__(self, document_id: _Optional[str] = ..., content: _Optional[str] = ..., score: _Optional[float] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...

class InitRequest(_message.Message):
__slots__ = ("connection_string", "collection_name")
CONNECTION_STRING_FIELD_NUMBER: _ClassVar[int]
COLLECTION_NAME_FIELD_NUMBER: _ClassVar[int]
connection_string: str
collection_name: str
def __init__(self, connection_string: _Optional[str] = ..., collection_name: _Optional[str] = ...) -> None: ...

class InitResponse(_message.Message):
__slots__ = ("success", "error")
SUCCESS_FIELD_NUMBER: _ClassVar[int]
ERROR_FIELD_NUMBER: _ClassVar[int]
success: bool
error: _common_pb2.Error
def __init__(self, success: _Optional[bool] = ..., error: _Optional[_Union[_common_pb2.Error, _Mapping]] = ...) -> None: ...

class EmbedScholarshipBatchRequest(_message.Message):
__slots__ = ("scholarships",)
SCHOLARSHIPS_FIELD_NUMBER: _ClassVar[int]
scholarships: _containers.RepeatedCompositeFieldContainer[Scholarship]
def __init__(self, scholarships: _Optional[_Iterable[_Union[Scholarship, _Mapping]]] = ...) -> None: ...

class EmbedScholarshipBatchResponse(_message.Message):
__slots__ = ("total_embedded", "error")
TOTAL_EMBEDDED_FIELD_NUMBER: _ClassVar[int]
ERROR_FIELD_NUMBER: _ClassVar[int]
total_embedded: int
error: _common_pb2.Error
def __init__(self, total_embedded: _Optional[int] = ..., error: _Optional[_Union[_common_pb2.Error, _Mapping]] = ...) -> None: ...

class Document(_message.Message):
__slots__ = ("document_id", "content", "metadata")
DOCUMENT_ID_FIELD_NUMBER: _ClassVar[int]
CONTENT_FIELD_NUMBER: _ClassVar[int]
METADATA_FIELD_NUMBER: _ClassVar[int]
document_id: str
content: str
metadata: _struct_pb2.Struct
def __init__(self, document_id: _Optional[str] = ..., content: _Optional[str] = ..., metadata: _Optional[_Union[_struct_pb2.Struct, _Mapping]] = ...) -> None: ...

class Scholarship(_message.Message):
__slots__ = ("id", "name", "description", "min_gpa", "eligible_majors", "citizenship_required", "location", "award_amount", "keywords")
ID_FIELD_NUMBER: _ClassVar[int]
NAME_FIELD_NUMBER: _ClassVar[int]
DESCRIPTION_FIELD_NUMBER: _ClassVar[int]
MIN_GPA_FIELD_NUMBER: _ClassVar[int]
ELIGIBLE_MAJORS_FIELD_NUMBER: _ClassVar[int]
CITIZENSHIP_REQUIRED_FIELD_NUMBER: _ClassVar[int]
LOCATION_FIELD_NUMBER: _ClassVar[int]
AWARD_AMOUNT_FIELD_NUMBER: _ClassVar[int]
KEYWORDS_FIELD_NUMBER: _ClassVar[int]
id: int
name: str
description: str
min_gpa: float
eligible_majors: _containers.RepeatedScalarFieldContainer[str]
citizenship_required: str
location: str
award_amount: str
keywords: _containers.RepeatedScalarFieldContainer[str]
def __init__(self, id: _Optional[int] = ..., name: _Optional[str] = ..., description: _Optional[str] = ..., min_gpa: _Optional[float] = ..., eligible_majors: _Optional[_Iterable[str]] = ..., citizenship_required: _Optional[str] = ..., location: _Optional[str] = ..., award_amount: _Optional[str] = ..., keywords: _Optional[_Iterable[str]] = ...) -> None: ...
Loading