-
Notifications
You must be signed in to change notification settings - Fork 8
Link insertion #118
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Link insertion #118
Changes from all commits
1af8568
97ffc9c
6bd539d
86f4209
3f6bf67
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| from pydantic_ai import Agent | ||
|
|
||
| from core.agents.models import get_default_ai_model | ||
| from core.agents.schemas import BlogPostGenerationContext | ||
| from core.agents.system_prompts import ( | ||
| add_language_specification, | ||
|
|
@@ -8,7 +9,6 @@ | |
| add_target_keywords, | ||
| add_title_details, | ||
| ) | ||
| from core.choices import get_default_ai_model | ||
|
|
||
|
|
||
| def create_content_editor_agent(model=None): | ||
|
|
@@ -31,13 +31,13 @@ def create_content_editor_agent(model=None): | |
| Your task is to edit the blog post content based on the requested changes. | ||
| """, | ||
| retries=2, | ||
| model_settings={"temperature": 0.3}, | ||
| model_settings={"temperature": 0.3, "thinking_budget": 0}, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainVerify the The 🌐 Web query: 💡 Result: Yes. Agent accepts model_settings and you can set a thinking_budget via a model-specific settings class — e.g., GoogleModelSettings supports google_thinking_config={'thinking_budget': ...} which can be passed to Agent (or at run time). [1][2] Sources: 🏁 Script executed: #!/bin/bash
# View the content_editor_agent.py file to see full context
cat core/agents/content_editor_agent.py | head -60Length of output: 1381 🏁 Script executed: #!/bin/bash
# Search for model initialization patterns in agents directory
rg -nP --type=py -C5 'model_settings.*thinking_budget' core/agents/Length of output: 8860 🏁 Script executed: #!/bin/bash
# Check what model is being used in this agent
rg -nP --type=py -C10 'class.*Agent|ClientModel|model=' core/agents/content_editor_agent.pyLength of output: 575 🏁 Script executed: #!/bin/bash
# Find all Agent instantiations in the agents directory
rg -nP --type=py 'Agent\(' core/agents/ -C3Length of output: 6583 🏁 Script executed: #!/bin/bash
# Check what get_default_ai_model returns
cat core/agents/models.pyLength of output: 362 🏁 Script executed: #!/bin/bash
# Check if there's requirements or setup to see pydantic-ai version
fd -e 'txt' -e 'toml' -e 'cfg' --type f | grep -E '(requirements|setup|pyproject|poetry)' | head -5Length of output: 43 🏁 Script executed: #!/bin/bash
# Search for any imports or usage of model settings structures
rg -nP --type=py 'ModelSettings|model_settings' core/agents/ -B2 -A2 | head -50Length of output: 3016 🏁 Script executed: #!/bin/bash
# Check pydantic-ai version
grep -A5 -B5 'pydantic.ai\|pydantic-ai' pyproject.toml requirements.txt 2>/dev/null | head -20Length of output: 1182 🌐 Web query: 💡 Result: Short answer — use the model-specific settings field (GoogleModelSettings.google_thinking_config) and pass a dict with key "thinking_budget". Example:
Agent-level model_settings are merged with model-level and run-time settings (run-time has highest precedence). [1][2][3] Sources: Incorrect parameter format for For pydantic-ai 1.9.1 with Google Gemini models, The current code at line 34: model_settings={"temperature": 0.3, "thinking_budget": 0}Should be corrected to use the model-specific settings structure. This issue affects multiple agents in 🤖 Prompt for AI Agents |
||
| ) | ||
|
|
||
| @agent.system_prompt | ||
| def only_return_the_edited_content() -> str: | ||
| return """ | ||
| IMPORTANT: Only return the edited content, no other text. | ||
| Only return the edited content, no other text. | ||
| """ | ||
|
|
||
| agent.system_prompt(add_project_details) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,8 +3,8 @@ | |
| from pydantic_ai.models.openai import OpenAIChatModel | ||
| from pydantic_ai.providers.openai import OpenAIProvider | ||
|
|
||
| from core.agents.models import AIModel | ||
| from core.agents.schemas import ProjectDetails | ||
| from core.choices import AIModel | ||
|
|
||
|
|
||
| def create_find_competitors_agent(is_on_free_plan: bool): | ||
|
|
@@ -70,22 +70,14 @@ def number_of_competitors(ctx: RunContext[ProjectDetails]) -> str: | |
| @agent.system_prompt | ||
| def language_specification(ctx: RunContext[ProjectDetails]) -> str: | ||
| project = ctx.deps | ||
| return f""" | ||
| IMPORTANT: Be mindful that competitors are likely to speak in | ||
| {project.language} language. | ||
| """ | ||
| return f"Be mindful that competitors are likely to speak in {project.language} language." # noqa: E501 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused The static analysis tool correctly identified that the Apply this diff to remove the unused directives: - return f"Be mindful that competitors are likely to speak in {project.language} language." # noqa: E501
+ return f"Be mindful that competitors are likely to speak in {project.language} language."- return f"Only return competitors whose target audience is in {project.location}." # noqa: E501
+ return f"Only return competitors whose target audience is in {project.location}."Also applies to: 79-79 🧰 Tools🪛 Ruff (0.14.4)73-73: Unused Remove unused (RUF100) 🤖 Prompt for AI Agents |
||
|
|
||
| @agent.system_prompt | ||
| def location_specification(ctx: RunContext[ProjectDetails]) -> str: | ||
| project = ctx.deps | ||
| if project.location != "Global": | ||
| return f""" | ||
| IMPORTANT: Only return competitors whose target audience is in | ||
| {project.location}. | ||
| """ | ||
| return f"Only return competitors whose target audience is in {project.location}." # noqa: E501 | ||
| else: | ||
| return """ | ||
| IMPORTANT: Return competitors from all over the world. | ||
| """ | ||
| return "Return competitors from all over the world." | ||
|
|
||
| return agent | ||
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,85 @@ | ||||||||||
| from pydantic_ai import Agent, RunContext | ||||||||||
|
|
||||||||||
| from core.agents.models import get_default_ai_model | ||||||||||
| from core.agents.schemas import InsertedLinksOutput, InsertInternalLinksContext | ||||||||||
|
|
||||||||||
|
|
||||||||||
| def create_insert_internal_links_agent(model=None): | ||||||||||
| """ | ||||||||||
| Create an agent to insert internal links into blog post content. | ||||||||||
| The agent takes existing blog post content and a list of internal pages, | ||||||||||
| then intelligently inserts links where they are contextually relevant. | ||||||||||
| Args: | ||||||||||
| model: Optional AI model to use. Defaults to the default AI model. | ||||||||||
| Returns: | ||||||||||
| Configured Agent instance | ||||||||||
| """ | ||||||||||
| system_prompt = """ | ||||||||||
| You are an expert content editor specializing in internal linking strategies for SEO optimization. | ||||||||||
| Your task is to take blog post content and intelligently insert internal links to relevant pages | ||||||||||
| where they naturally fit and add value to the reader. | ||||||||||
| ## Guidelines for Link Insertion: | ||||||||||
| 1. **Natural Integration**: Insert links only where they enhance the reader's understanding or provide valuable additional context. Links should feel organic and not forced. | ||||||||||
| 2. **Contextual Relevance**: Match the page's topic with the surrounding content. Only link when there's a clear topical connection. | ||||||||||
| 3. **Anchor Text**: Use descriptive, natural anchor text that clearly indicates what the reader will find when clicking the link. Avoid generic phrases like "click here" or "this page". | ||||||||||
| 4. **Strategic Placement**: | ||||||||||
| - Prefer linking in the main body content rather than introductions or conclusions | ||||||||||
| - Space out links appropriately - avoid clustering multiple links in a single paragraph | ||||||||||
| - Link to each page at most once or twice in the entire article | ||||||||||
| 5. **Must-Use Pages**: These are high-priority pages that should be linked if there's any reasonable contextual fit. Be creative in finding natural places to mention and link to these pages. | ||||||||||
| 6. **Optional Pages**: Only link to these if they are highly relevant to the specific section of content where they would be inserted. | ||||||||||
| 7. **Markdown Format**: Use proper Markdown link syntax: `[anchor text](URL)` | ||||||||||
| 8. **Preserve Content**: Do not modify the existing content except to add links. Maintain all formatting, structure, and tone. | ||||||||||
| 9. **Quality Over Quantity**: It's better to have fewer, highly relevant links than many loosely related ones. | ||||||||||
| ## Output Requirements: | ||||||||||
| Return the complete blog post content with internal links inserted. The content should be in Markdown format with proper link syntax. | ||||||||||
| """ # noqa: E501 | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove unused The static analysis tool correctly identified that the Apply this diff: ## Output Requirements:
Return the complete blog post content with internal links inserted. The content should be in Markdown format with proper link syntax.
-""" # noqa: E501
+"""📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.14.4)51-51: Unused Remove unused (RUF100) 🤖 Prompt for AI Agents |
||||||||||
|
|
||||||||||
| agent = Agent( | ||||||||||
| model or get_default_ai_model(), | ||||||||||
| output_type=InsertedLinksOutput, | ||||||||||
| deps_type=InsertInternalLinksContext, | ||||||||||
| system_prompt=system_prompt, | ||||||||||
| retries=2, | ||||||||||
| model_settings={"max_tokens": 65500, "temperature": 0.3, "thinking_budget": 0}, | ||||||||||
| ) | ||||||||||
|
|
||||||||||
| @agent.system_prompt | ||||||||||
| def add_must_use_and_optional_pages(ctx: RunContext[InsertInternalLinksContext]) -> str: | ||||||||||
| return f""" | ||||||||||
| Must-use pages: | ||||||||||
| {ctx.deps.must_use_pages} | ||||||||||
| -------------------------------- | ||||||||||
| Optional pages: | ||||||||||
| {ctx.deps.optional_pages} | ||||||||||
| """ | ||||||||||
|
|
||||||||||
| @agent.system_prompt | ||||||||||
| def add_content(ctx: RunContext[InsertInternalLinksContext]) -> str: | ||||||||||
| return f""" | ||||||||||
| Content: | ||||||||||
| -------------------------------- | ||||||||||
| {ctx.deps.content} | ||||||||||
| -------------------------------- | ||||||||||
| """ | ||||||||||
|
|
||||||||||
| @agent.system_prompt | ||||||||||
| def output() -> str: | ||||||||||
| return "Return only the post that I gave you, but with links." | ||||||||||
|
|
||||||||||
| return agent | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| from django.db import models | ||
|
|
||
|
|
||
| class AIModel(models.TextChoices): | ||
| GEMINI_FLASH = "google-gla:gemini-2.5-flash", "Gemini 2.5 Flash" | ||
| PERPLEXITY_SONAR = "sonar", "Perplexity Sonar" | ||
|
|
||
|
|
||
| DEFAULT_AI_MODEL = AIModel.GEMINI_FLASH | ||
|
|
||
|
|
||
| def get_default_ai_model() -> str: | ||
| """Returns the default AI model to use across the application.""" | ||
| return DEFAULT_AI_MODEL | ||
|
Comment on lines
+1
to
+14
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainLGTM: Clean centralization of AI model configuration. The new module provides a clean, centralized location for AI model definitions. The structure follows Django conventions with TextChoices and provides a clear default model selection mechanism. However, please verify the model identifier "google-gla:gemini-2.5-flash" is correct. The "google-gla" prefix appears unusual for Gemini models. 🌐 Web query: 💡 Result: The correct model identifier is "gemini-2.5-flash". [1][2] Sources: Fix incorrect model identifier for Google Gemini 2.5 Flash. The correct model identifier for Google Gemini 2.5 Flash in pydantic-ai is "gemini-2.5-flash", not "google-gla:gemini-2.5-flash". Update line 5 in core/agents/models.py: GEMINI_FLASH = "gemini-2.5-flash", "Gemini 2.5 Flash"The incorrect prefix will cause runtime failures when pydantic-ai attempts to load the model. 🤖 Prompt for AI Agents |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix extra whitespace in system prompt.
Line 26 contains multiple consecutive spaces: "Make reasonable inferences based". This appears to be a formatting error.
Apply this diff to fix the spacing:
📝 Committable suggestion
🤖 Prompt for AI Agents