Skip to content

Commit 6382c77

Browse files
authored
feat: add ollama provider and new openai models (gpt-oss:20b and gpt-oss:120b) (#30)
1 parent 30c5860 commit 6382c77

19 files changed

Lines changed: 220 additions & 43 deletions

File tree

README.md

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,6 @@
2727

2828
---
2929

30-
> ⚠️ **Alpha Release**
31-
>
32-
> Codius is currently in alpha.
33-
> Features may be incomplete, unstable, or subject to change.
34-
> Use with care in production environments — and help shape it by providing feedback or contributing!
35-
36-
---
37-
3830
## Why Codius?
3931

4032
> Free domain-driven designers from boilerplate and let them focus on modeling.

poetry.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,15 @@ dependencies = [
2626
"jinja2",
2727
"langgraph",
2828
"langchain-openai",
29-
"py-dependency-injection >=1.0.0b3,<2.0.0",
3029
"python-dateutil",
3130
"python-dotenv",
3231
"pyyaml",
3332
"prompt-toolkit",
3433
"rich",
3534
"tree-sitter==0.23.2",
3635
"tree-sitter-c-sharp",
37-
"typing-extensions"
36+
"typing-extensions",
37+
"py-dependency-injection (>=1.0.0rc2,<2.0.0)",
3838
]
3939

4040
[tool.poetry.group.dev]

src/codius/di.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33
from dependency_injection.container import DependencyContainer
44

55
from codius.domain.model.config.config import Config
6+
from codius.domain.model.config.llm_provider import LlmProvider
67
from codius.domain.model.port.llm_port import LlmPort
78
from codius.domain.services.config_service import ConfigService
89
from codius.domain.services.session_service import SessionService
10+
from codius.infrastructure.adapter.llm.ollama.ollama_llm_adapter import OllamaLlmAdapter
911

1012
from codius.infrastructure.adapter.llm.openai.openai_llm_adapter import OpenAiLlmAdapter
1113
from codius.infrastructure.repository.session_repository import SessionRepository
@@ -52,4 +54,16 @@ def register_services(config: Config, args: argparse.Namespace):
5254
container.register_scoped(OpenDddConventionService)
5355
container.register_scoped(TreeSitterService)
5456
container.register_scoped(LlmService)
55-
container.register_scoped(LlmPort, OpenAiLlmAdapter)
57+
58+
adapter_by_provider = {
59+
LlmProvider.OPENAI: OpenAiLlmAdapter,
60+
LlmProvider.OLLAMA: OllamaLlmAdapter,
61+
}
62+
63+
provider = config.llm.provider
64+
adapter_cls = adapter_by_provider.get(provider)
65+
66+
if adapter_cls is None:
67+
raise RuntimeError(f"Unsupported LLM provider in config: {provider}")
68+
69+
container.register_scoped(LlmPort, adapter_cls)

src/codius/domain/model/config/config.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
"openai": {
1010
"model": "gpt-4o",
1111
"api_key": "sk-... # Replace with your OpenAI API key"
12+
},
13+
"anthropic": {
14+
"model": "claude-3-opus",
15+
"api_key": "xyz-... # Replace with your Anthropic API key"
16+
},
17+
"ollama": {
18+
"base_url": "http://localhost:11434",
19+
"model": "gpt-oss:20b"
1220
}
1321
},
1422
"approval_mode": ApprovalMode.SUGGEST.value,

src/codius/domain/model/config/llm_provider.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ class LlmProvider(str, Enum):
77
GOOGLE = "google"
88
MISTRAL = "mistral"
99
GROQ = "groq"
10+
OLLAMA = "ollama"

src/codius/domain/model/config/ollama/__init__.py

Whitespace-only changes.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from enum import Enum
2+
3+
4+
class OllamaModel(str, Enum):
5+
GPT_OSS_20B = "gpt-oss:20b"
6+
GPT_OSS_120B = "gpt-oss:120b"
7+
LLAMA_31_8B = "llama3.1:8b-instruct-q4_K_M"
8+
MISTRAL_7B = "mistral:7b"

src/codius/domain/model/intents/intent_type.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
from enum import Enum
22

3+
from codius.infrastructure.services.code_scanner.model.building_block_type import \
4+
BuildingBlockType
5+
36

47
class IntentType(str, Enum):
58
ADD_AGGREGATE = "add_aggregate"
@@ -22,3 +25,17 @@ class IntentType(str, Enum):
2225
REMOVE_REPOSITORY_METHOD = "remove_repository_method"
2326

2427
UNSURE = "unsure"
28+
29+
@property
30+
def building_block(self) -> BuildingBlockType:
31+
if self.name.startswith("ADD_AGGREGATE") or self.name.startswith(
32+
"REMOVE_AGGREGATE"):
33+
return BuildingBlockType.AGGREGATE_ROOT
34+
elif self.name.startswith("ADD_VALUE_OBJECT") or self.name.startswith(
35+
"REMOVE_VALUE_OBJECT"):
36+
return BuildingBlockType.VALUE_OBJECT
37+
elif self.name.startswith("ADD_REPOSITORY") or self.name.startswith(
38+
"REMOVE_REPOSITORY"):
39+
return BuildingBlockType.REPOSITORY
40+
else:
41+
raise NotImplementedError(f"Building block not mapped for intent {self}")

src/codius/domain/model/prompts/distill_intent_prompt.py

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
from codius.domain.model.intents.value_object.add_value_object_property_intent import AddValueObjectPropertyIntent
2323
from codius.domain.model.intents.value_object.remove_value_object_property_intent import RemoveValueObjectPropertyIntent
2424
from codius.domain.model.intents.repository.add_repository_intent import AddRepositoryIntent
25+
from codius.infrastructure.services.code_scanner.model.building_block_type import \
26+
BuildingBlockType
2527

2628

2729
@dataclass(frozen=True)
@@ -49,6 +51,14 @@ def as_prompt(self) -> str:
4951
RemoveRepositoryMethodIntent,
5052
]
5153

54+
all_blocks = {bb.value for bb in BuildingBlockType}
55+
supported_blocks = {intent.building_block.value for intent in IntentType if
56+
intent != IntentType.UNSURE}
57+
unsupported_blocks = all_blocks - supported_blocks
58+
59+
supported_blocks_text = "\n".join(f"- {b}" for b in sorted(supported_blocks))
60+
unsupported_blocks_text = "\n".join(f"- {b}" for b in sorted(unsupported_blocks))
61+
5262
example_blocks = "\n".join(
5363
f"### {cls.intent.value}\n```json\n{cls.to_example_json()}\n```"
5464
for cls in example_intents
@@ -88,6 +98,29 @@ def as_prompt(self) -> str:
8898
**Database Providers**:
8999
{database_text}
90100
101+
---
102+
103+
### Known DDD Building Blocks
104+
105+
These are the known building blocks in Domain-Driven Design:
106+
107+
**Supported:**
108+
{supported_blocks_text}
109+
110+
**Not yet supported:**
111+
{unsupported_blocks_text}
112+
113+
If the user refers to a known DDD building block that is **not yet supported**, return:
114+
115+
```json
116+
{{ "intent": "unsupported", "building_block": "<block_name>" }}
117+
```
118+
119+
If the user's intent is unclear or unsupported, respond only with:
120+
121+
```json
122+
{{ "intent": "unsure" }}
123+
91124
### Instructions
92125
93126
- Break complex modeling instructions into small, **granular intents**.
@@ -109,9 +142,4 @@ def as_prompt(self) -> str:
109142
### Examples:
110143
111144
{example_blocks}
112-
113-
If the user's intent is unclear or unsupported, respond only with:
114-
115-
```json
116-
{{ "intent": "unsure" }}
117145
"""

0 commit comments

Comments
 (0)