mirror of
https://github.com/NCBM/plyngent.git
synced 2026-07-23 05:55:16 +08:00
docs: add architecture notes and development principles
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project overview
|
||||
|
||||
Plyngent is an LLM chat and agent toolkit (Python 3.14+, PDM-managed). It is in early development — core protocol clients exist, while agent, CLI, web, memory, and config modules are planned but not yet implemented.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
pdm install # first-time dependency setup
|
||||
pdm sync # sync after pulling changes
|
||||
|
||||
pdm run basedpyright . # type checking (basedpyright, "recommended" strictness)
|
||||
pdm run ruff check . # linting
|
||||
pdm run ruff format . # formatting
|
||||
```
|
||||
|
||||
There is no test runner configured yet.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Data modeling: `msgspec.Struct`
|
||||
|
||||
All protocol models use `msgspec.Struct` — not dataclasses, not Pydantic. This gives type-safe, schema-validated structs with efficient JSON codec support. Use `msgspec.field(default=UNSET)` for optional fields to distinguish "not provided" from `None`.
|
||||
|
||||
The `Unset` type alias (`typedef.py`) wraps `msgspec.UNSET` as `Literal[UnsetType.UNSET]`. `JSONSchema` is `dict[str, Any]`.
|
||||
|
||||
### Protocol layering (`lmproto/`)
|
||||
|
||||
```
|
||||
lmproto/openai_compatible/ ← Base: model, config, client
|
||||
lmproto/deepseek/openai_compat/ ← Extends base via inheritance + extra fields
|
||||
```
|
||||
|
||||
- **`openai_compatible/model.py`** — chat message models (`SystemChatMessage`, `UserChatMessage`, `AssistantChatMessage`, `ToolChatMessage`), tool definitions, request/response structs, streaming chunks. All `msgspec.Struct` with `rename="snake"` for camelCase JSON interop.
|
||||
- **`openai_compatible/client.py`** — `BaseOpenAIClient` using `niquests` for async HTTP with SSE streaming. Two response modes: `ChatCompletionResponse` (non-streaming) and `AsyncIterator[ChatCompletionChunk]` (streaming).
|
||||
- **`openai_compatible/config.py`** — `OpenAIConfig` dataclass (base URL, API key, model name, max tokens, temperature).
|
||||
- **DeepSeek extension** — `DeepseekOpenAIClient` extends `BaseOpenAIClient`. Models add `reasoning_content`, `prefix`, `ThinkingOptions`, and `DeepSeekReasoningEffort` (including `"max"`).
|
||||
|
||||
### Composition utility: `Forward` descriptor
|
||||
|
||||
`utils/components.py` provides a `Forward[T]` descriptor for forwarding attribute access to a composed sub-object — prefer composition over inheritance where appropriate. The `forward()` factory function constructs `Forward` instances with type inference.
|
||||
|
||||
### Type annotations are mandatory
|
||||
|
||||
Basedpyright in `recommended` mode (strictest preset). Ruff lint rules include `ANN` (flake8-annotations) — all functions must have type annotations except private functions (`ANN202` suppressed). Use PEP 695 `type X = ...` syntax for type aliases. Python 3.14+ generics syntax is expected.
|
||||
|
||||
## Commit messages
|
||||
|
||||
Scoped commit messages, not conventional commits:
|
||||
|
||||
```
|
||||
<scope>: <brief description>
|
||||
```
|
||||
|
||||
Examples: `deps: add fastapi`, `core/mq: fix incorrect message sending`, `router: add routing service for xxx`, `test/webserver: change test client`, `ci/lint: run ruff style check`.
|
||||
|
||||
Check `git log` for the full convention.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Code Architecture
|
||||
|
||||
- plyngent
|
||||
- typedef: Shared type aliases.
|
||||
- lmproto: Protocols for interacting with LLM service.
|
||||
- (common)
|
||||
- model: Messages models of specified providers.
|
||||
- config: Configurations for specified providers.
|
||||
- client: Clients for accessing existent specified services.
|
||||
- server: Servers for accepting other clients.
|
||||
- openai
|
||||
- openai_compatible
|
||||
- anthropic
|
||||
- ollama
|
||||
- deepseek
|
||||
- openai_compat
|
||||
- anthropic
|
||||
- utils: Common utilities for code architecture.
|
||||
- components: Utilities for class composition.
|
||||
- memory: Storage controlling for sessions and messages.
|
||||
- router: Multi-source capability routing and interception.
|
||||
- interceptors: Capability of stealing a few arguments for partial re-routing.
|
||||
- ...
|
||||
- config: Plyngent configuration center.
|
||||
- agent: Agent capabilities and controlling.
|
||||
- tools: Client code of tool calls.
|
||||
- cli: CLI for chat/agent application.
|
||||
- web: Web service for chat/agent application.
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# Development Principles
|
||||
|
||||
## If you are new to project
|
||||
|
||||
### Have a general overview of the project
|
||||
|
||||
You should at least have a clear view of the general architecture. This aims for:
|
||||
|
||||
1. keeping the style of codebase consistent.
|
||||
2. using or extending existing objects or functions instead of writing new but duplicate code, since the latter is usually a kind of **SHIT**.
|
||||
|
||||
For a general architecture reference, see [here](./architecture.md).
|
||||
|
||||
This does not mean you should immediately grasp the whole codebase, but **you should not make changes until you have a clear view of the general architecture**.
|
||||
|
||||
### Commit messages
|
||||
|
||||
This project uses scoped commit message. Examples:
|
||||
|
||||
- `project: init`: initializing a new project.
|
||||
- `deps: add fastapi`: add/upgrade/removing a dependency.
|
||||
- `deps/dev: upgrade ruff`: add/upgrade/removing a dev dependency.
|
||||
- `core/mq: fix incorrect message sending`, `router: add routing service for xxx`: add/change/fix/refactor/removing functional code.
|
||||
- `test/webserver: change test client to niquests`: add/change/fix/refactor/removing tests.
|
||||
- `scripts/i18n: implement dumping translation keys`: add/change/fix/refactor/removing general scripts.
|
||||
- `ci/lint: run ruff style check`, `ci/build: fix changelog generation`: add/change/fix/refactor/removing CI workflows.
|
||||
|
||||
Once conventional commit was good, until redundant forms like `fix: fix ...`, `refactor: refactor ...` came up. So we use scoped commit message here.
|
||||
|
||||
If you are still not quite familiar to this, check the git log in any way you prefer.
|
||||
|
||||
## General information and suggestions
|
||||
|
||||
### Local development environment
|
||||
|
||||
Syncing packages: `pdm install` the first time, then `pdm sync`. The former can fully initialize the dependencies, and the latter can continuously keep consistent dependencies.
|
||||
|
||||
For other commands like adding or removing packages, see [PDM Documentation](https://pdm-project.org/en/latest/usage/dependency/). These commands usually updates lock file automatically by default, so `pdm sync` should only be used when after `git pull/fetch/checkout`.
|
||||
|
||||
### Type checking and linting
|
||||
|
||||
Firstly, we prefer using `pdm run <command/script>` to directly running commands in venv (whether in activated environment or not).
|
||||
|
||||
Then for every projects, check the dev dependency group where you can find tools used for type checking and linting.
|
||||
|
||||
Type checking: `pdm run basedpyright .`
|
||||
Linting: `pdm run ruff check .`
|
||||
Formating: `pdm run ruff format .`
|
||||
|
||||
<!-- Contents in comments are for projects with long-period developments, but this is a new project.
|
||||
|
||||
### Branches
|
||||
|
||||
In most cases, we do not need and should not make bare commits on the main branch.
|
||||
|
||||
### Tests
|
||||
|
||||
...
|
||||
|
||||
-->
|
||||
Reference in New Issue
Block a user