No description
Find a file
autocommit 0b5739299f
Some checks failed
Publish / publish (push) Failing after 0s
Publish to PyPI / Build and Publish (push) Failing after 53s
deps-upgrade(build-system): ⬆️ Update build dependencies to latest versions in pyproject.toml
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
2026-04-12 00:21:39 -07:00
.forgejo/workflows chore: initial commit with DRY workflow 2026-01-21 12:49:00 -08:00
dist chore: initial commit with DRY workflow 2026-01-21 12:49:00 -08:00
src/ml_style_adapter chore: initial commit with DRY workflow 2026-01-21 12:49:00 -08:00
tests chore: initial commit with DRY workflow 2026-01-21 12:49:00 -08:00
pyproject.toml deps-upgrade(build-system): ⬆️ Update build dependencies to latest versions in pyproject.toml 2026-04-12 00:21:39 -07:00
README.md chore: initial commit with DRY workflow 2026-01-21 12:49:00 -08:00

ML Style Adapter

Learn and apply user communication styles for personalized text generation.

Installation

pip install lilith-ml-style-adapter

For LLM-based style transfer (optional):

pip install lilith-ml-style-adapter[model-router]

Quick Start

from ml_style_adapter import StyleAdapter, StyleProfile, TrainingSample

adapter = StyleAdapter()

# Learn from training samples
profile = await adapter.learn_style([
    TrainingSample(input="How are you?", output="Good! You?"),
    TrainingSample(input="Meeting tomorrow?", output="yep, see you there"),
])

# Apply style to generated response
styled = await adapter.apply_style(
    response="I am doing well, thank you for asking.",
    profile=profile
)
# Returns: "good! you?"

Style Profile Dimensions

The StyleProfile captures these communication patterns:

Dimension Type Description
formality float (0.0-1.0) Casual (0) to formal (1)
emoji_usage bool Whether emojis are used
avg_length int Average response length in characters
punctuation_style enum minimal, standard, or expressive
capitalization enum lowercase, standard, or uppercase
common_phrases list Frequently used phrases/patterns
contraction_preference float (0.0-1.0) Preference for contractions
response_brevity float (0.0-1.0) How brief responses tend to be

Style Analysis Heuristics

The analyzer examines:

  • Formality: Word choice, contractions, sentence structure
  • Emoji: Presence/frequency of emoji characters
  • Length: Average character count across samples
  • Punctuation: Use of !, ?, ..., and terminal punctuation
  • Capitalization: Pattern of lowercase/uppercase usage
  • Contractions: Frequency of contracted forms

Style Application

Transformations applied in order:

  1. Adjust response length (truncate based on brevity)
  2. Apply formality level (add/remove contractions, vocabulary)
  3. Match capitalization pattern
  4. Adjust punctuation style
  5. Add/remove emojis based on profile

LLM-Based Style Transfer (Optional)

For more sophisticated semantic style transfer, provide an LLM provider:

from ml_model_router import ModelRouter

router = ModelRouter(
    fast_model="ministral-3b-instruct",
    reasoning_model="ministral-14b-reasoning",
)

# Wrap router to match LLMProvider protocol
class RouterWrapper:
    def __init__(self, router):
        self.router = router

    async def generate(self, prompt: str) -> str:
        # Use your model router to generate
        result = await self.router.generate(prompt)
        return result.text

adapter = StyleAdapter(llm_provider=RouterWrapper(router))

# Use LLM for transformation
styled = await adapter.apply_style(response, profile, use_llm=True)

API Reference

StyleAdapter

Main class for learning and applying styles.

adapter = StyleAdapter(llm_provider=None)

# Learn style from samples
profile = await adapter.learn_style(samples: List[TrainingSample]) -> StyleProfile

# Apply style to text
styled = await adapter.apply_style(
    response: str,
    profile: StyleProfile,
    use_llm: bool = False
) -> str

# Convenience: learn and apply in one call
styled, profile = await adapter.learn_and_apply(
    samples: List[TrainingSample],
    response: str,
    use_llm: bool = False
) -> tuple[str, StyleProfile]

TrainingSample

Input/output pair for style learning:

sample = TrainingSample(
    input="How are you?",   # The prompt/question
    output="Good! You?"     # The response in target style
)

StyleProfile

Captured style dimensions (can also be manually constructed):

from ml_style_adapter import StyleProfile, PunctuationStyle, CapitalizationStyle

profile = StyleProfile(
    formality=0.3,
    emoji_usage=False,
    avg_length=12,
    punctuation_style=PunctuationStyle.MINIMAL,
    capitalization=CapitalizationStyle.LOWERCASE,
    common_phrases=["sounds good", "see you"],
    contraction_preference=0.8,
    response_brevity=0.7,
)

Examples

Casual Style

samples = [
    TrainingSample(input="Status update?", output="all good here"),
    TrainingSample(input="ETA?", output="like 5 mins"),
    TrainingSample(input="Thoughts?", output="yeah looks cool"),
]

profile = await adapter.learn_style(samples)
# formality: ~0.2, punctuation: minimal, capitalization: lowercase

result = await adapter.apply_style(
    "I believe this is an excellent proposal.",
    profile
)
# Returns: "yeah this is cool"

Formal Style

samples = [
    TrainingSample(
        input="Project status?",
        output="The project is proceeding according to schedule."
    ),
    TrainingSample(
        input="Can we reschedule?",
        output="Certainly. Please propose alternative times."
    ),
]

profile = await adapter.learn_style(samples)
# formality: ~0.8, punctuation: standard, capitalization: standard

result = await adapter.apply_style(
    "yeah we can do that",
    profile
)
# Returns: "Yes, we can do that."

Development

# Install dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Run with coverage
pytest --cov=ml_style_adapter

License

MIT