Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
e3578c2
Add initial pyproject.toml
mart-r Aug 27, 2026
54d89d3
Add initial LLM component code
mart-r Aug 27, 2026
6e928c7
Add pytest as test-time dependency
mart-r Aug 27, 2026
a61e967
Add creation method to linker
mart-r Aug 27, 2026
016d5c1
Fix forward reference
mart-r Aug 27, 2026
024452f
Minor linting tweaks
mart-r Aug 27, 2026
6c7b581
Add creation method to ner component
mart-r Aug 27, 2026
c40d0fc
Fix issue with component types
mart-r Aug 27, 2026
98667d7
Fix typo
mart-r Aug 27, 2026
85cfb62
Add simple registration tests
mart-r Aug 27, 2026
7cc65cd
Add workflow for LLM components
mart-r Aug 27, 2026
095dbd5
Make sure NER component sets dected name
mart-r Aug 27, 2026
2e4aacc
Update tests to include new arguments
mart-r Aug 27, 2026
19970e6
Separate linked entities from NER entities in LLM implementation
mart-r Aug 27, 2026
3806f2b
Add a few tests with mock server as well
mart-r Aug 27, 2026
c4910ac
Fix small linting issue
mart-r Aug 27, 2026
d203cc8
Fix small linting issue - for real
mart-r Aug 27, 2026
d693f67
Add spacy/meta-cat optional extras to deps
mart-r Aug 28, 2026
6cf05eb
Make linker set similairity and accuracy to 1
mart-r Aug 28, 2026
f189af8
Add fix for incoming markdown table
mart-r Aug 28, 2026
67955b7
Add link candidates to entities
mart-r Aug 28, 2026
b55fc22
Fix minor issue with confidence/accuracy setting for linker
mart-r Aug 28, 2026
193be14
Minor linting (ruff) fix
mart-r Aug 28, 2026
9e3a1ba
Add names to linker and ner component (to show up in pipe description)
mart-r Aug 28, 2026
9ec2d57
Fix minor linting issue
mart-r Aug 28, 2026
c1550a2
Added README with examples
mart-r Aug 28, 2026
4affc7b
Merge branch 'main' into feat/medcat-llm-components/CPDT-108-add-LLM-…
mart-r Aug 28, 2026
480961c
Fix local install reference in workflow
mart-r Aug 28, 2026
8a2e1f5
Fix doc string r-prefix
mart-r Aug 28, 2026
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
110 changes: 110 additions & 0 deletions .github/workflows/medcat-llm-components_ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
name: medcat-llm-components - CI (test | publish)

on:
push:
branches: [ main ]
tags:
- 'medcat-llm-components/v*.*.*'
pull_request:
paths:
- 'medcat-plugins/llm-comps/**'
- '.github/workflows/medcat-llm-components**'

permissions:
id-token: write

defaults:
run:
working-directory: ./medcat-plugins/llm-comps

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [ '3.10', '3.11', '3.12' ]
max-parallel: 4
steps:
- uses: actions/checkout@v7
- name: Install uv for Python ${{ matrix.python-version }}
uses: astral-sh/setup-uv@v7
with:
python-version: ${{ matrix.python-version }}
enable-cache: true
- name: Install the project
run: |
uv sync --all-extras --dev
uv run python -m ensurepip
uv run python -m pip install --upgrade pip
uv run python -m pip install "../../medcat[spacy]"
- name: Check types
run: |
uv run python -m mypy --follow-imports=normal src/medcat_llm_components
- name: Ruff linting
run: |
uv run ruff check src/medcat_llm_components --preview
- name: Test
run: |
uv run python -m pytest tests

publish-to-test-PyPI:
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout main
uses: actions/checkout@v7
with:
fetch-depth: 0 # fetch all history
fetch-tags: true # fetch tags explicitly

- name: Install uv for Python 3.10
uses: astral-sh/setup-uv@v7
with:
python-version: '3.10'
enable-cache: true

- name: Install dependencies
run: |
uv run python -m ensurepip

- name: Set timestamp-based dev version
run: |
TS=$(date -u +"%Y%m%d%H%M%S")
echo "SETUPTOOLS_SCM_PRETEND_VERSION_FOR_MEDCAT_LLM_COMPONENTS=0.2.2.dev${TS}" >> $GITHUB_ENV

- name: Build package
run: |
uv build

- name: Publish distribution to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository_url: https://test.pypi.org/legacy/
packages_dir: medcat-plugins/llm-comps/dist

publish-to-PyPI:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/')
needs: build
steps:
- name: Checkout main
uses: actions/checkout@v7

- name: Install uv for Python 3.10
uses: astral-sh/setup-uv@v7
with:
python-version: '3.10'
enable-cache: true

- name: Install dependencies
run: |
uv run python -m ensurepip

- name: Build client package
run: |
uv build

- name: Publish production distribution to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
packages_dir: medcat-plugins/llm-comps/dist
114 changes: 114 additions & 0 deletions medcat-plugins/llm-comps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
## MedCAT LLM component examples

This project aims to provide a few simple examples for LLM based components (for NER and/or linking).

**These are not designed to be the best implementation. They are designed as an example.**

### How to install

```
pip install medcat-llm-components
```

### How to use

#### Add to existing model

This way you can use the CDB already tied to the model.

```python
from medcat.cat import CAT
from medcat_llm_components.ner import LLMNERConfig
from medcat_llm_components.linker import LLMLinkConfig
### INPUT ###
# existing model
model_path = ""
# the URL to the (e.g) ollama instance
base_url = "my_ollama_ip:port/whatever"
# the model to use
llm_model = "gemma:2b"

### AUTOMATION ###
# NOTE: don't need to use both NER and linker
# we just have one example for both
cat = CAT.load_model_pack(model_path)
# create configs
# ner
ner_cnf = LLMNERConfig(
base_url=base_url,
model=llm_model,
# for other optional arguments such as prompt
# refer to code or IDE inspection
)
# linker
linking_cnf = LLMLinkConfig(
base_url=base_url,
model=llm_model,
# for other optional arguments such as prompt
# refer to code or IDE inspection
)
# update model pack
# ner
cat.config.components.ner.comp_name = "llm_ner"
# NOTE: different path for NER and linker
cat.config.components.ner.custom_cnf = ner_cnf
# linking
cat.config.components.linking.comp_name = "llm_linker"
# NOTE: different path for NER and linker
cat.config.components.linking.additional = linking_cnf
# recreate pipe
cat._recreate_pipe()

print(cat.describe_pipeline())
# ready to use!
print(cat.get_entities("Anhedonia"))
```

### Create as part of a new model pack

You can create a new model pack yourself.
This will almost certainly be more involved.

```python
from medcat.cat import CAT
from medcat.cdb import CDB
from medcat.config import Config

from medcat_llm_components.ner import LLMNERConfig
from medcat_llm_components.linker import LLMLinkConfig

# the URL to the (e.g) ollama instance
base_url = "my_ollama_ip:port/whatever"
# the model to use
llm_model = "gemma:2b"

# create configs
# ner
ner_cnf = LLMNERConfig(
base_url=base_url,
model=llm_model,
# for other optional arguments such as prompt
# refer to code or IDE inspection
)
# linker
linking_cnf = LLMLinkConfig(
base_url=base_url,
model=llm_model,
# for other optional arguments such as prompt
# refer to code or IDE inspection
)

config = Config()# update model pack
config.components.ner.comp_name = "llm_ner"
config.components.ner.custom_cnf = ner_cnf
config.components.linking.comp_name = "llm_linker"
config.components.linking.additional = linking_cnf

vocab = Vocab()
# or load a CDB on its own with CDB.load("my_cdb.zip")
cdb = CDB(config)

cat = CAT(cdb, vocab)
print(cat.describe_pipeline())
# ready to use!
```
63 changes: 63 additions & 0 deletions medcat-plugins/llm-comps/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[build-system]
requires = ["setuptools>=61.0", "wheel", "setuptools_scm>=8"]
build-backend = "setuptools.build_meta"

[project]
name = "medcat_llm_components"
dynamic = ["version"]
description = ""
readme = "README.md"
license = { text = "Apache-2.0" }
authors = [
{ name="Mart Ratas", email="mart.ratas@kcl.ac.uk" }
]
requires-python = ">=3.10"

keywords = ["MedCAT"]

classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Science/Research",
"Topic :: Scientific/Engineering :: Artificial Intelligence",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"License :: OSI Approved :: Apache Software License"
]

dependencies = [
"medcat[spacy,meta-cat]>=2.5",
"pydantic",
"openai~=3.3.1",
]

[project.optional-dependencies]
dev = [
"ruff",
"mypy",
"pytest",
]

# entry-points to add onto medcat
[project.entry-points."medcat.plugins"]
llm_components = "medcat_llm_components"

[project.urls]
Homepage = "https://github.com/CogStack/cogstack-nlp/tree/main/medcat-plugins/llm-comps"
Repository = "https://github.com/CogStack/cogstack-nlp/tree/main/medcat-plugins/llm-comps"
Issues = "https://github.com/CogStack/cogstack-nlp/issues"

[tool.setuptools_scm]
root = "../.."
tag_regex = "^medcat-llm-components/v(?P<version>\\d+(?:\\.\\d+)*)(?:[ab]\\d+|rc\\d+)?$"
version_scheme = "post-release"
local_scheme = "no-local-version"
git_describe_command = "git describe --dirty --tags --long --match 'medcat-llm-components/v*'"

[tool.setuptools.packages.find]
where = ["src"]

[tool.setuptools.package-data]
"medcat_llm_components" = ["py.typed"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .registration import do_registration as __register

__register()
Loading
Loading