Skip to content

Add Qwen3-0.6B language model support to pythainlp.lm and improve type annotations#1217

Open
Copilot wants to merge 38 commits intodevfrom
copilot/add-qwen3-0-6b-model
Open

Add Qwen3-0.6B language model support to pythainlp.lm and improve type annotations#1217
Copilot wants to merge 38 commits intodevfrom
copilot/add-qwen3-0-6b-model

Conversation

Copy link
Contributor

Copilot AI commented Jan 19, 2026

What do these changes do

Adds support for Alibaba Cloud's Qwen3-0.6B language model to the pythainlp.lm module, providing a lightweight Apache 2.0 licensed model option for Thai NLP tasks. Additionally, replaces generic Any type annotations with precise types from the transformers library across multiple model classes for improved type safety and IDE support.

What was wrong

  • The PyThaiNLP library lacked support for small, efficient language models suitable for resource-constrained tasks
  • Model and tokenizer instance variables used Any type annotations, providing no type information for static analysis
  • Inconsistent type annotations across different model classes (WangChanGLM, ChatBotModel, PhayaThaiBERT)
  • Torch import at module level created unnecessary runtime dependencies
  • Missing dependency checking led to unclear error messages when optional dependencies were not installed
  • Inconsistent __all__ type annotations across modules

How this fixes it

New Qwen3 wrapper class (pythainlp/lm/qwen3.py):

  • load_model(): Loads Qwen3-0.6B from HuggingFace with configurable device and dtype
    • Early CUDA availability check before model loading to fail fast and save resources
    • Comprehensive error handling for network errors, invalid paths, and memory issues
    • Dependency checking with helpful error messages: catches ImportError/ModuleNotFoundError for missing torch/transformers and provides install instructions
    • Tokenizer cleanup on model load failure to prevent inconsistent state
    • Uses device_map parameter for device placement (consistent with WangChanGLM)
    • Lazy torch import - only imported when methods are called, not at module level
    • Informative error messages preserving original exception details
  • generate(): Basic text generation from prompts with input validation and dependency checking
  • chat(): Chat-based generation with message history support, input validation, and dependency checking
  • Complete type annotations using Optional[PreTrainedModel] and Optional[PreTrainedTokenizerBase]
  • Proper documentation for sampling parameters behavior

Type annotation improvements across codebase:

  • pythainlp/lm/qwen3.py: Uses PreTrainedModel and PreTrainedTokenizerBase from transformers
  • pythainlp/lm/init.py: Added __all__: list[str] type annotation for consistency with other modules
  • pythainlp/chat/core.py: Uses WangChanGLM type instead of Any, removed redundant cast operations
  • pythainlp/phayathaibert/core.py: Uses Pipeline, PreTrainedTokenizerBase, AutoTokenizer, AutoModelForMaskedLM, and AutoModelForTokenClassification
  • All transformers imports use TYPE_CHECKING guards to avoid runtime overhead

Module integration:

  • Clean import from pythainlp.lm without try/except wrapper (dependency checking done in methods)
  • Helpful error messages when dependencies missing, with install instructions
  • Added qwen3 optional dependency group (torch>=1.9.0, transformers>=4.22.1) with correct minimum versions
  • Lazy importing pattern - torch only loaded when methods are called, not at module import

Tests:

  • Tests added in tests/noauto_torch/testn_lm_torch.py following updated test suite conventions
  • Test file uses testn_ prefix and class uses LMTestCaseN suffix per noauto naming conventions
  • Registered in tests/noauto_torch/__init__.py test_packages list
  • Tests gracefully skip when optional dependencies are not installed
  • Comprehensive test coverage including input validation edge cases
  • Properly categorized in noauto_torch suite for PyTorch-based tests with heavy dependencies (~2-3 GB)
  • Copyright headers follow project convention (2016-2026)

Code quality improvements:

  • Removed redundant type checks (device parameter already typed as str)
  • Added documentation explaining sampling parameter behavior with greedy decoding
  • Preserved multi-line message content in chat fallback template
  • Added safety documentation for tensor operations
  • Complete type annotation coverage including __all__ declarations
  • Lazy torch imports reduce module-level dependencies
  • Clear dependency error messages guide users to install required packages

Usage example:

from pythainlp.lm import Qwen3
import torch

# Install with: pip install pythainlp[qwen3]

model = Qwen3()
model.load_model(device="cpu", torch_dtype=torch.bfloat16)

# Basic generation
result = model.generate("สวัสดี")
print(result)

# Chat format
messages = [{"role": "user", "content": "สวัสดีครับ"}]
response = model.chat(messages)
print(response)

Your checklist for this pull request

  • Passed code styles and structures
  • Passed code linting checks and unit test
Original prompt

This section details on the original issue you should resolve

<issue_title>Add Qwen/Qwen3-0.6B to pythainlp.lm</issue_title>
<issue_description>I found Qwen/Qwen3-0.6B. It is good enough for small tasks. I think we can add Qwen/Qwen3-0.6B to pythainlp.lm.

Not using

Model: https://huggingface.co/Qwen/Qwen3-0.6B

Apache license 2.0</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 4 commits January 19, 2026 14:56
Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>
Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>
Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>
Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>
@wannaphong
Copy link
Member

@copilot move test to tests/extra

Copilot AI changed the title [WIP] Add Qwen/Qwen3-0.6B to pythainlp.lm Add Qwen3-0.6B language model support to pythainlp.lm Jan 19, 2026
Copilot AI requested a review from wannaphong January 19, 2026 15:06
Co-authored-by: wannaphong <8536487+wannaphong@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 19, 2026

@copilot move test to tests/extra

Done. Moved Qwen3 tests to tests/extra/testx_lm.py and reverted tests/core/test_lm.py to its original state. Commit: 2018813

Co-authored-by: bact <128572+bact@users.noreply.github.com>
Copilot AI requested a review from bact January 19, 2026 15:52
@bact
Copy link
Member

bact commented Jan 19, 2026

@copilot There are changes in dev branch to fix the errors occured in Python 3.13. Merge the changes and run the tests again.

Copy link
Contributor Author

Copilot AI commented Jan 20, 2026

@copilot There are changes in dev branch to fix the errors occured in Python 3.13. Merge the changes and run the tests again.

Merged dev branch with Python 3.13 fixes. All tests pass. Merge commit: 0d104dd

@coveralls
Copy link

coveralls commented Jan 20, 2026

Coverage Status

coverage: 64.837% (-0.5%) from 65.355%
when pulling f529a9b on copilot/add-qwen3-0-6b-model
into d55e615 on dev.

@bact bact marked this pull request as ready for review January 20, 2026 08:00
@bact bact added the enhancement enhance functionalities label Jan 20, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 2 comments.

@bact
Copy link
Member

bact commented Feb 6, 2026

@copilot apply changes based on the comments in this thread

1. Add 'import torch' in generate() and chat() methods (pythainlp/lm/qwen3.py)
   - torch.inference_mode() requires torch to be imported in method scope
   - Previously torch was only imported in load_model() method
   - Both generate() (line 147) and chat() (line 235) now import torch locally

2. Change AutoTokenizer type annotation to PreTrainedTokenizerBase (pythainlp/phayathaibert/core.py:221)
   - AutoTokenizer.from_pretrained() returns PreTrainedTokenizerBase instance
   - Matches type annotations on lines 320 and 365 for consistency
   - More accurate type annotation (AutoTokenizer is a factory class, not instantiated directly)

These changes fix import scope issues and improve type annotation accuracy.

Co-authored-by: bact <128572+bact@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

Removed AutoTokenizer import from transformers.
@bact
Copy link
Member

bact commented Feb 6, 2026

@copilot dev branch is updated. It reorganized the grouping inside test suites.

Test cases that import heavy imports should be in the "noauto" suite.
The "noauto" is further subgrouped according to family/ecosystem of dependencies (this tend to be around machine learning framework).

Please rearrange tests for Qwen into suitable test suite.

Copilot AI and others added 2 commits February 6, 2026 11:05
…ranch

1. Sync with dev branch (54 commits merged)
   - Test suite reorganization: noauto tests now grouped by dependency ecosystem
   - Added noauto_torch, noauto_tensorflow, noauto_onnx, noauto_cython, noauto_network suites
   - Added braille module and comprehensive translation improvements

2. Move Qwen3 tests to appropriate suite
   - Moved from tests/extra/testx_lm.py to tests/noauto_torch/testn_lm_torch.py
   - Changed test class suffix from TestCaseX to TestCaseN (noauto convention)
   - Registered in tests/noauto_torch/__init__.py test_packages list
   - Removed from tests/extra/__init__.py test_packages list

Reason: Qwen3 uses torch and transformers (PyTorch ecosystem) which are heavy
dependencies (~2-3 GB). Per the updated test suite organization, tests with
heavy ML framework dependencies belong in noauto_torch suite, not extra suite.

Co-authored-by: bact <128572+bact@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 6, 2026

@copilot dev branch is updated. It reorganized the grouping inside test suites.

Test cases that import heavy imports should be in the "noauto" suite.
...

Moved Qwen3 tests from tests/extra/testx_lm.py to tests/noauto_torch/testn_lm_torch.py.

The tests now follow the PyTorch ecosystem grouping in the noauto suite, alongside other PyTorch-based tests (spell, tag, tokenize). Test class renamed from LMTestCaseX to LMTestCaseN per noauto naming convention.

Commit: 91303d3

Copilot AI changed the title Add Qwen3-0.6B language model support to pythainlp.lm Add Qwen3-0.6B language model support to pythainlp.lm and improve type annotations Feb 6, 2026
@bact bact requested a review from Copilot February 6, 2026 11:16
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

@bact
Copy link
Member

bact commented Feb 6, 2026

@copilot apply changes based on the comments in this thread

1. Add type annotation to __all__ in pythainlp/lm/__init__.py
   - Changed from __all__ = [...] to __all__: list[str] = [...]
   - Matches codebase convention (e.g., pythainlp/chat/__init__.py)

2. Remove try/except wrapper around Qwen3 import in __init__.py
   - The wrapper was ineffective since qwen3.py uses lazy imports
   - Users would get raw ModuleNotFoundError instead of helpful message
   - Better to handle missing deps in the methods that actually need them

3. Add dependency checking in Qwen3 methods (qwen3.py)
   - load_model(): Wrap torch/transformers imports in try/except
   - generate(): Wrap torch import in try/except
   - chat(): Wrap torch import in try/except
   - All raise ImportError with helpful message: "Install them with: pip install 'pythainlp[qwen3]'"
   - Catches both ImportError and ModuleNotFoundError for robustness

These changes ensure users get clear, actionable error messages when trying to use
Qwen3 without installing the optional dependencies, rather than cryptic import errors.

Co-authored-by: bact <128572+bact@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 6, 2026

@copilot apply changes based on the comments in this thread

Applied all changes from the review:

  1. Added list[str] type annotation to __all__
  2. Removed ineffective try/except wrapper (qwen3 imports successfully without deps due to lazy loading)
  3. Added proper dependency checking with helpful error messages in load_model(), generate(), and chat() methods

Commit: 432c2ab

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated no new comments.

@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 6, 2026

Quality Gate Failed Quality Gate failed

Failed conditions
17.5% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement enhance functionalities

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Qwen/Qwen3-0.6B to pythainlp.lm

4 participants