Skip to content

Random LLM - #34

Open
TrangOul wants to merge 21 commits into
horw:mainfrom
TrangOul:main
Open

Random LLM#34
TrangOul wants to merge 21 commits into
horw:mainfrom
TrangOul:main

Conversation

@TrangOul

Copy link
Copy Markdown

Closes #11

Comment thread src/core/settings.py
Comment thread src/main.py Outdated
from core.llm import create_ai_client
from core.settings import Config
from core.verbose import set_verbose
from src.core.github_client import GitHubClient

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Before this change:

ImportError while importing test module '(...)\horw-issue-title-ai\tests\test_main.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
(...)\Python313\Lib\importlib\__init__.py:88: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
tests\test_main.py:5: in <module>
    from src.main import open_issue_event, run, scan_issue_event
src\main.py:6: in <module>
    from core.github_client import GitHubClient
E   ModuleNotFoundError: No module named 'core'

@horw horw Apr 30, 2025

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Hmm, looks good to me. How did you run the tests? I just ran:

pytest

in the project directory.

@TrangOul TrangOul Apr 30, 2025

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I originally ran pytest --cov=src --cov-report=xml --cov-report=html --html=test-report.html --self-contained-html in the project root dir (on Windows, if that matters). Now I've re-tested it with just pytest, after reverting the addition of src., and the same error occurs.

@horw horw Apr 30, 2025

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

So it would be nice if you could say how I can reproduce it.

my logs:

(venv) horw@horw-ProArt-P16-H7606WI-H7606WI:~/PycharmProjects/issue-title-ai$ pytest
==================================================================== test session starts =====================================================================
platform linux -- Python 3.11.12, pytest-8.3.5, pluggy-1.5.0
rootdir: /home/horw/PycharmProjects/issue-title-ai
configfile: pyproject.toml
plugins: anyio-4.9.0, socket-0.7.0, cov-6.1.1
collected 68 items                                                                                                                                           

tests/test_github_client.py .............                                                                                                              [ 19%]
tests/test_issue_service.py ...........                                                                                                                [ 35%]
tests/test_llm.py .................                                                                                                                    [ 60%]
tests/test_main.py ......                                                                                                                              [ 69%]
tests/test_settings.py .....................                                                                                                           [100%]

======================================================================= tests coverage =======================================================================
______________________________________________________ coverage: platform linux, python 3.11.12-final-0 ______________________________________________________

Name                        Stmts   Miss Branch BrPart  Cover   Missing
-----------------------------------------------------------------------
src/core/github_client.py      48      1      8      1    96%   39
src/core/issue_service.py      46      0     12      0   100%
src/core/llm.py                64      0     12      0   100%
src/core/settings.py           98      0     34      1    99%   37->41
src/core/verbose.py            11      1      2      1    85%   7
src/main.py                    53      2      8      2    93%   45, 90
-----------------------------------------------------------------------
TOTAL                         320      4     76      5    98%
Coverage HTML written to dir htmlcov
Required test coverage of 80.0% reached. Total coverage: 97.73%
===================================================================== 68 passed in 0.94s =====================================================================
(venv) horw@horw-ProArt-P16-H7606WI-H7606WI:~/PycharmProjects/issue-title-ai$ 


Comment thread tests/test_settings.py
@TrangOul

TrangOul commented Apr 29, 2025

Copy link
Copy Markdown
Author

No AI-improved title for this PR? :(
(This can be a future improvement.)

Comment thread src/core/settings.py
@horw

horw commented Apr 30, 2025

Copy link
Copy Markdown
Owner

No AI-improved title for this PR? :( (This can be a future improvement.)

With PRs, it seems harder to achieve this. Actually, it's okay to just look at the PR description, but as I see it, developers usually don't put much effort into the description. So, the main source of truth becomes the diffs — but that makes things more difficult (for sure, not that much more—just a few more steps):

  • You need to get the diffs first
  • Understand whether the description is good
  • Use the description and/or diffs to change the title

Comment thread tests/test_settings.py
@horw

horw commented Apr 30, 2025

Copy link
Copy Markdown
Owner

Thank you for this PR! I just left a few comments. Your solution looks good!

Comment thread src/core/settings.py Outdated
if self.explicit_provider:
return self.ai_providers[self.explicit_provider]

ai_provider = random.choice(list(self.ai_providers.keys())) # nosec

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

@horw, I hope this nosec is OK?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Since Ruff raises this error, use # noqa: S311 to skip it.

@TrangOul

TrangOul commented Apr 30, 2025

Copy link
Copy Markdown
Author

Fixes #35 (quick fix, not with pathlib).

Comment thread src/core/settings.py Outdated
Comment thread src/main.py Outdated
Comment thread src/core/settings.py Outdated
Comment on lines +124 to +134
return ai_providers

@property
def ai_provider(self):
if self.ai_providers:
if self.explicit_provider:
return self.ai_providers[self.explicit_provider]

ai_provider = random.choice(list(self.ai_providers.keys()))
return self.ai_providers[ai_provider]
raise ValueError("No LLM API key was provided. Please provide one of the following: deepseek, gemini, openai.")

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
return ai_providers
@property
def ai_provider(self):
if self.ai_providers:
if self.explicit_provider:
return self.ai_providers[self.explicit_provider]
ai_provider = random.choice(list(self.ai_providers.keys()))
return self.ai_providers[ai_provider]
raise ValueError("No LLM API key was provided. Please provide one of the following: deepseek, gemini, openai.")
if not self.ai_providers:
raise ValueError(
"No LLM API key was provided. Please provide one of the following: deepseek, gemini, openai."
)
return ai_providers
@property
def ai_provider(self):
ai_provider = random.choice(list(self.ai_providers.keys()))
return self.ai_providers[ai_provider]

How about we move the login check for No LLM ... into _get_llm_config? That way, ai_provider looks much simpler. WDYT?

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Then in the validation function, ai_provider = self.ai_provider is not needed.

Comment thread src/core/settings.py Outdated
"deepseek": self.deepseek_api_key,
}
self.explicit_provider = os.environ.get("INPUT_AI-PROVIDER", "").lower()
self._get_llm_configs()

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I preferred how it was before, with the return value ai_providers, which was then assigned to self.ai_providers. The current function is named get_llm_configs, but in reality, it is doing a setting operation.

Comment thread src/core/settings.py Outdated
def ai_provider(self):
ai_provider_name = self.ai_providers[self.explicit_provider] \
if self.explicit_provider \
else ai_provider = random.choice(list(self.ai_providers.keys())) # noqa: S311

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Syntax error : else ai_provider = random...

Also, I don't think using a one-line if-else for a long expression is a good idea—it can easily be converted to a regular if-else statement.

Comment thread src/core/settings.py
Comment on lines +132 to +137
@property
def ai_provider(self):
ai_provider_name = self.ai_providers[self.explicit_provider] \
if self.explicit_provider \
else ai_provider = random.choice(list(self.ai_providers.keys())) # noqa: S311
return self.ai_providers[ai_provider_name]

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
@property
def ai_provider(self):
ai_provider_name = self.ai_providers[self.explicit_provider] \
if self.explicit_provider \
else ai_provider = random.choice(list(self.ai_providers.keys())) # noqa: S311
return self.ai_providers[ai_provider_name]
@property
def ai_provider(self):
ai_provider = random.choice(list(self.ai_providers.keys()))
return self.ai_providers[ai_provider]

WDYT about this solution? Yes, it might call random.choice a few more times, even when there's only one element, but code looks simple

@TrangOul

Copy link
Copy Markdown
Author

@horw, any update? Could you run the workflows, please (or configure them to run automatically)?

@horw

horw commented May 16, 2025

Copy link
Copy Markdown
Owner

@horw, any update? Could you run the workflows, please (or configure them to run automatically)?

Hi! In the workflow, there are two jobs: one is the pre-commit hook, and the other is running pytest. You can easily run them locally with:

pytest

and

pre-commit run --all-files

@TrangOul

Copy link
Copy Markdown
Author

Thanks @horw, I think now all the checks should pass. On my machine only the compile requirements.txt step fails (some issue with WSL), but it passes here.

@TrangOul

Copy link
Copy Markdown
Author

@horw, since the tests pass now, are we OK with merging this?

@horw

horw commented May 22, 2025

Copy link
Copy Markdown
Owner

Hi, I will review this PR.

One note: we've changed the API, so users who already use our action will encounter a problem because the model parameter no longer exists. We can add a message to the user, such as: "The model attribute is deprecated; please use ... instead."

After you add this, I will help to fix the pre-commit issue, and then we will be ready to merge it.

@TrangOul

TrangOul commented Jun 2, 2025

Copy link
Copy Markdown
Author

@horw, I've added the deprecation message. Please check whether it is OK.

@TrangOul

TrangOul commented Sep 3, 2025

Copy link
Copy Markdown
Author

@horw, any update with this?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add LLM rotation.

2 participants