fabricatio 0.3.15.dev4__cp312-cp312-win_amd64.whl → 0.4.4__cp312-cp312-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. fabricatio/__init__.py +7 -8
  2. fabricatio/actions/__init__.py +69 -1
  3. fabricatio/capabilities/__init__.py +59 -1
  4. fabricatio/models/__init__.py +47 -0
  5. fabricatio/rust.cp312-win_amd64.pyd +0 -0
  6. fabricatio/toolboxes/__init__.py +2 -1
  7. fabricatio/toolboxes/arithmetic.py +1 -1
  8. fabricatio/toolboxes/fs.py +2 -2
  9. fabricatio/workflows/__init__.py +9 -0
  10. fabricatio-0.4.4.data/scripts/tdown.exe +0 -0
  11. {fabricatio-0.3.15.dev4.dist-info → fabricatio-0.4.4.dist-info}/METADATA +49 -25
  12. fabricatio-0.4.4.dist-info/RECORD +15 -0
  13. fabricatio/actions/article.py +0 -415
  14. fabricatio/actions/article_rag.py +0 -407
  15. fabricatio/actions/fs.py +0 -25
  16. fabricatio/actions/output.py +0 -248
  17. fabricatio/actions/rag.py +0 -96
  18. fabricatio/actions/rules.py +0 -83
  19. fabricatio/capabilities/advanced_judge.py +0 -20
  20. fabricatio/capabilities/advanced_rag.py +0 -61
  21. fabricatio/capabilities/censor.py +0 -105
  22. fabricatio/capabilities/check.py +0 -212
  23. fabricatio/capabilities/correct.py +0 -228
  24. fabricatio/capabilities/extract.py +0 -74
  25. fabricatio/capabilities/persist.py +0 -103
  26. fabricatio/capabilities/propose.py +0 -65
  27. fabricatio/capabilities/rag.py +0 -264
  28. fabricatio/capabilities/rating.py +0 -404
  29. fabricatio/capabilities/review.py +0 -114
  30. fabricatio/capabilities/task.py +0 -113
  31. fabricatio/decorators.py +0 -253
  32. fabricatio/emitter.py +0 -177
  33. fabricatio/fs/__init__.py +0 -35
  34. fabricatio/fs/curd.py +0 -153
  35. fabricatio/fs/readers.py +0 -61
  36. fabricatio/journal.py +0 -12
  37. fabricatio/models/action.py +0 -263
  38. fabricatio/models/adv_kwargs_types.py +0 -63
  39. fabricatio/models/extra/__init__.py +0 -1
  40. fabricatio/models/extra/advanced_judge.py +0 -32
  41. fabricatio/models/extra/aricle_rag.py +0 -286
  42. fabricatio/models/extra/article_base.py +0 -486
  43. fabricatio/models/extra/article_essence.py +0 -101
  44. fabricatio/models/extra/article_main.py +0 -286
  45. fabricatio/models/extra/article_outline.py +0 -46
  46. fabricatio/models/extra/article_proposal.py +0 -52
  47. fabricatio/models/extra/patches.py +0 -20
  48. fabricatio/models/extra/problem.py +0 -165
  49. fabricatio/models/extra/rag.py +0 -98
  50. fabricatio/models/extra/rule.py +0 -52
  51. fabricatio/models/generic.py +0 -812
  52. fabricatio/models/kwargs_types.py +0 -121
  53. fabricatio/models/role.py +0 -99
  54. fabricatio/models/task.py +0 -310
  55. fabricatio/models/tool.py +0 -328
  56. fabricatio/models/usages.py +0 -791
  57. fabricatio/parser.py +0 -114
  58. fabricatio/rust.pyi +0 -846
  59. fabricatio/utils.py +0 -156
  60. fabricatio/workflows/articles.py +0 -24
  61. fabricatio/workflows/rag.py +0 -11
  62. fabricatio-0.3.15.dev4.data/scripts/tdown.exe +0 -0
  63. fabricatio-0.3.15.dev4.data/scripts/ttm.exe +0 -0
  64. fabricatio-0.3.15.dev4.dist-info/RECORD +0 -64
  65. {fabricatio-0.3.15.dev4.dist-info → fabricatio-0.4.4.dist-info}/WHEEL +0 -0
  66. {fabricatio-0.3.15.dev4.dist-info → fabricatio-0.4.4.dist-info}/licenses/LICENSE +0 -0
fabricatio/actions/rag.py DELETED
@@ -1,96 +0,0 @@
1
- """Inject data into the database."""
2
-
3
- from typing import List, Optional
4
-
5
- from fabricatio.capabilities.rag import RAG
6
- from fabricatio.journal import logger
7
- from fabricatio.models.action import Action
8
- from fabricatio.models.extra.rag import MilvusClassicModel, MilvusDataBase
9
- from fabricatio.models.task import Task
10
- from fabricatio.rust import CONFIG
11
- from fabricatio.utils import ok
12
-
13
-
14
- class InjectToDB(Action, RAG):
15
- """Inject data into the database."""
16
-
17
- output_key: str = "collection_name"
18
- collection_name: str = "my_collection"
19
- """The name of the collection to inject data into."""
20
-
21
- async def _execute[T: MilvusDataBase](
22
- self, to_inject: Optional[T] | List[Optional[T]], override_inject: bool = False, **_
23
- ) -> Optional[str]:
24
- from pymilvus.milvus_client import IndexParams
25
-
26
- if to_inject is None:
27
- return None
28
- if not isinstance(to_inject, list):
29
- to_inject = [to_inject]
30
- if not (seq := [t for t in to_inject if t is not None]): # filter out None
31
- return None
32
- logger.info(f"Injecting {len(seq)} items into the collection '{self.collection_name}'")
33
- if override_inject:
34
- self.check_client().client.drop_collection(self.collection_name)
35
-
36
- await self.view(
37
- self.collection_name,
38
- create=True,
39
- schema=seq[0].as_milvus_schema(
40
- ok(
41
- self.milvus_dimensions
42
- or CONFIG.rag.milvus_dimensions
43
- or self.embedding_dimensions
44
- or CONFIG.embedding.dimensions
45
- ),
46
- ),
47
- index_params=IndexParams(
48
- seq[0].vector_field_name,
49
- index_name=seq[0].vector_field_name,
50
- index_type=seq[0].index_type,
51
- metric_type=seq[0].metric_type,
52
- ),
53
- ).add_document(seq, flush=True)
54
-
55
- return self.collection_name
56
-
57
-
58
- class RAGTalk(Action, RAG):
59
- """RAG-enabled conversational action that processes user questions based on a given task.
60
-
61
- This action establishes an interactive conversation loop where it retrieves context-relevant
62
- information to answer user queries according to the assigned task briefing.
63
-
64
- Notes:
65
- task_input: Task briefing that guides how to respond to user questions
66
- collection_name: Name of the vector collection to use for retrieval (default: "my_collection")
67
-
68
- Returns:
69
- Number of conversation turns completed before termination
70
- """
71
-
72
- output_key: str = "task_output"
73
-
74
- async def _execute(self, task_input: Task[str], **kwargs) -> int:
75
- from questionary import text
76
-
77
- collection_name = kwargs.get("collection_name", "my_collection")
78
- counter = 0
79
-
80
- self.view(collection_name, create=True)
81
-
82
- try:
83
- while True:
84
- user_say = await text("User: ").ask_async()
85
- if user_say is None:
86
- break
87
- ret: List[MilvusClassicModel] = await self.aretrieve(user_say, document_model=MilvusClassicModel)
88
-
89
- gpt_say = await self.aask(
90
- user_say, system_message="\n".join(m.text for m in ret) + "\nYou can refer facts provided above."
91
- )
92
- print(f"GPT: {gpt_say}") # noqa: T201
93
- counter += 1
94
- except KeyboardInterrupt:
95
- logger.info(f"executed talk action {counter} times")
96
- return counter
@@ -1,83 +0,0 @@
1
- """A module containing the DraftRuleSet action."""
2
-
3
- from typing import Any, List, Mapping, Optional, Self, Tuple
4
-
5
- from fabricatio.capabilities.check import Check
6
- from fabricatio.journal import logger
7
- from fabricatio.models.action import Action
8
- from fabricatio.models.extra.rule import RuleSet
9
- from fabricatio.models.generic import FromMapping
10
- from fabricatio.utils import ok
11
-
12
-
13
- class DraftRuleSet(Action, Check, FromMapping):
14
- """Action to draft a ruleset based on a given requirement description."""
15
-
16
- output_key: str = "drafted_ruleset"
17
- """The key used to store the drafted ruleset in the context dictionary."""
18
-
19
- ruleset_requirement: Optional[str] = None
20
- """The natural language description of the desired ruleset characteristics."""
21
- rule_count: int = 0
22
- """The number of rules to generate in the ruleset (0 for no restriction)."""
23
-
24
- async def _execute(
25
- self,
26
- ruleset_requirement: Optional[str] = None,
27
- **_,
28
- ) -> Optional[RuleSet]:
29
- """Draft a ruleset based on the requirement description.
30
-
31
- Args:
32
- ruleset_requirement (str): Natural language description of desired ruleset characteristics
33
- rule_count (int): Number of rules to generate (0 for no restriction)
34
- **kwargs: Validation parameters for rule generation
35
-
36
- Returns:
37
- Optional[RuleSet]: Drafted ruleset object or None if generation fails
38
- """
39
- ruleset = await self.draft_ruleset(
40
- ruleset_requirement=ok(ruleset_requirement or self.ruleset_requirement, "No ruleset requirement provided"),
41
- rule_count=self.rule_count,
42
- )
43
- if ruleset:
44
- logger.info(f"Drafted Ruleset length: {len(ruleset.rules)}\n{ruleset.display()}")
45
- else:
46
- logger.warning(f"Drafting Rule Failed for:\n{ruleset_requirement}")
47
- return ruleset
48
-
49
- @classmethod
50
- def from_mapping(cls, mapping: Mapping[str, Tuple[int, str]], **kwargs) -> List[Self]:
51
- """Create a list of DraftRuleSet actions from a mapping of output keys to tuples of rule counts and requirements."""
52
- return [cls(ruleset_requirement=r, rule_count=c, output_key=k, **kwargs) for k, (c, r) in mapping.items()]
53
-
54
-
55
- class GatherRuleset(Action, FromMapping):
56
- """Action to gather a ruleset from a given requirement description."""
57
-
58
- output_key: str = "gathered_ruleset"
59
- """The key used to store the drafted ruleset in the context dictionary."""
60
-
61
- to_gather: List[str]
62
- """the cxt name of RuleSet to gather"""
63
-
64
- @classmethod
65
- def from_mapping(cls, mapping: Mapping[str, List[str]], **kwargs: Any) -> List[Self]:
66
- """Create a list of GatherRuleset actions from a mapping of output keys to tuples of rule counts and requirements."""
67
- return [cls(to_gather=t, output_key=k, **kwargs) for k, t in mapping.items()]
68
-
69
- async def _execute(self, **cxt) -> RuleSet:
70
- logger.info(f"Gathering Ruleset from {self.to_gather}")
71
- # Fix for not_found
72
- not_found = next((t for t in self.to_gather if t not in cxt), None)
73
- if not_found:
74
- raise ValueError(
75
- f"Not all required keys found in context: {self.to_gather}|`{not_found}` not found in context."
76
- )
77
-
78
- # Fix for invalid RuleSet check
79
- invalid = next((t for t in self.to_gather if not isinstance(cxt[t], RuleSet)), None)
80
- if invalid is not None:
81
- raise TypeError(f"Invalid RuleSet instance for key `{invalid}`")
82
-
83
- return RuleSet.gather(*[cxt[t] for t in self.to_gather])
@@ -1,20 +0,0 @@
1
- """The Capabilities module for advanced judging."""
2
-
3
- from abc import ABC
4
- from typing import Optional, Unpack
5
-
6
- from fabricatio.capabilities.propose import Propose
7
- from fabricatio.models.extra.advanced_judge import JudgeMent
8
- from fabricatio.models.kwargs_types import ValidateKwargs
9
-
10
-
11
- class AdvancedJudge(Propose, ABC):
12
- """A class that judges the evidence and makes a final decision."""
13
-
14
- async def evidently_judge(
15
- self,
16
- prompt: str,
17
- **kwargs: Unpack[ValidateKwargs[JudgeMent]],
18
- ) -> Optional[JudgeMent]:
19
- """Judge the evidence and make a final decision."""
20
- return await self.propose(JudgeMent, prompt, **kwargs)
@@ -1,61 +0,0 @@
1
- """Advanced RAG (Retrieval Augmented Generation) model."""
2
-
3
- from abc import ABC
4
- from typing import Optional, Unpack
5
-
6
- from fabricatio.capabilities.rag import RAG
7
- from fabricatio.journal import logger
8
- from fabricatio.models.adv_kwargs_types import FetchKwargs
9
- from fabricatio.models.extra.aricle_rag import ArticleChunk, CitationManager
10
- from fabricatio.models.kwargs_types import ChooseKwargs
11
- from fabricatio.utils import fallback_kwargs
12
-
13
-
14
- class AdvancedRAG(RAG, ABC):
15
- """A class representing the Advanced RAG (Retrieval Augmented Generation) model."""
16
-
17
- async def clued_search(
18
- self,
19
- requirement: str,
20
- cm: CitationManager,
21
- max_capacity: int = 40,
22
- max_round: int = 3,
23
- expand_multiplier: float = 1.4,
24
- base_accepted: int = 12,
25
- refinery_kwargs: Optional[ChooseKwargs] = None,
26
- **kwargs: Unpack[FetchKwargs],
27
- ) -> CitationManager:
28
- """Asynchronously performs a clued search based on a given requirement and citation manager."""
29
- if max_round <= 0:
30
- raise ValueError("max_round should be greater than 0")
31
- if max_round == 1:
32
- logger.warning(
33
- "max_round should be greater than 1, otherwise it behaves nothing different from the `self.aretrieve`"
34
- )
35
-
36
- refinery_kwargs = refinery_kwargs or {}
37
-
38
- for i in range(1, max_round + 1):
39
- logger.info(f"Round [{i}/{max_round}] search started.")
40
- ref_q = await self.arefined_query(
41
- f"{cm.as_prompt()}\n\nAbove is the retrieved references in the {i - 1}th RAG, now we need to perform the {i}th RAG."
42
- f"\n\n{requirement}",
43
- **refinery_kwargs,
44
- )
45
-
46
- if ref_q is None:
47
- logger.error(f"At round [{i}/{max_round}] search, failed to refine the query, exit.")
48
- return cm
49
- refs = await self.aretrieve(
50
- ref_q, ArticleChunk, base_accepted, **fallback_kwargs(kwargs, filter_expr=cm.as_milvus_filter_expr())
51
- )
52
-
53
- if (max_capacity := max_capacity - len(refs)) < 0:
54
- cm.add_chunks(refs[0:max_capacity])
55
- logger.debug(f"At round [{i}/{max_round}] search, the capacity is not enough, exit.")
56
- return cm
57
-
58
- cm.add_chunks(refs)
59
- base_accepted = int(base_accepted * expand_multiplier)
60
- logger.debug(f"Exceeded max_round: {max_round}, exit.")
61
- return cm
@@ -1,105 +0,0 @@
1
- """Module for censoring objects and strings based on provided rulesets.
2
-
3
- This module includes the Censor class which inherits from both Correct and Check classes.
4
- It provides methods to censor objects and strings by first checking them against a ruleset and then correcting them if necessary.
5
- """
6
-
7
- from abc import ABC
8
- from typing import Optional, Unpack
9
-
10
- from fabricatio.capabilities.check import Check
11
- from fabricatio.capabilities.correct import Correct
12
- from fabricatio.journal import logger
13
- from fabricatio.models.extra.problem import Improvement
14
- from fabricatio.models.extra.rule import RuleSet
15
- from fabricatio.models.generic import ProposedUpdateAble, SketchedAble
16
- from fabricatio.models.kwargs_types import ReferencedKwargs
17
- from fabricatio.utils import override_kwargs
18
-
19
-
20
- class Censor(Correct, Check, ABC):
21
- """Class to censor objects and strings based on provided rulesets.
22
-
23
- Inherits from both Correct and Check classes.
24
- Provides methods to censor objects and strings by first checking them against a ruleset and then correcting them if necessary.
25
-
26
- """
27
-
28
- async def censor_obj[M: SketchedAble](
29
- self, obj: M, ruleset: RuleSet, **kwargs: Unpack[ReferencedKwargs[M]]
30
- ) -> Optional[M]:
31
- """Censors an object based on the provided ruleset.
32
-
33
- Args:
34
- obj (M): The object to be censored.
35
- ruleset (RuleSet): The ruleset to apply for censoring.
36
- **kwargs: Additional keyword arguments to be passed to the check and correct methods.
37
-
38
- Returns:
39
- Optional[M]: The censored object if corrections were made, otherwise None.
40
-
41
- Note:
42
- This method first checks the object against the ruleset and then corrects it if necessary.
43
- """
44
- imp = await self.check_obj(obj, ruleset, **override_kwargs(kwargs, default=None))
45
- if imp is None:
46
- return None
47
- if not imp:
48
- logger.info(f"No improvement found for `{obj.__class__.__name__}`.")
49
- return obj
50
- logger.info(f"Generated {len(imp)} improvement(s) for `{obj.__class__.__name__}")
51
- return await self.correct_obj(obj, Improvement.gather(*imp), **kwargs)
52
-
53
- async def censor_string(
54
- self, input_text: str, ruleset: RuleSet, **kwargs: Unpack[ReferencedKwargs[str]]
55
- ) -> Optional[str]:
56
- """Censors a string based on the provided ruleset.
57
-
58
- Args:
59
- input_text (str): The string to be censored.
60
- ruleset (RuleSet): The ruleset to apply for censoring.
61
- **kwargs: Additional keyword arguments to be passed to the check and correct methods.
62
-
63
- Returns:
64
- Optional[str]: The censored string if corrections were made, otherwise None.
65
-
66
- Note:
67
- This method first checks the string against the ruleset and then corrects it if necessary.
68
- """
69
- imp = await self.check_string(input_text, ruleset, **override_kwargs(kwargs, default=None))
70
- if imp is None:
71
- logger.warning(f"Censor failed for string:\n{input_text}")
72
- return None
73
- if not imp:
74
- logger.info("No improvement found for string.")
75
- return input_text
76
- logger.info(f"Generated {len(imp)} improvement(s) for string.")
77
- return await self.correct_string(input_text, Improvement.gather(*imp), **kwargs)
78
-
79
- async def censor_obj_inplace[M: ProposedUpdateAble](
80
- self, obj: M, ruleset: RuleSet, **kwargs: Unpack[ReferencedKwargs[M]]
81
- ) -> Optional[M]:
82
- """Censors an object in-place based on the provided ruleset.
83
-
84
- This method modifies the object directly if corrections are needed.
85
-
86
- Args:
87
- obj (M): The object to be censored.
88
- ruleset (RuleSet): The ruleset to apply for censoring.
89
- **kwargs: Additional keyword arguments to be passed to the check and correct methods.
90
-
91
- Returns:
92
- Optional[M]: The censored object if corrections were made, otherwise None.
93
-
94
- Note:
95
- This method first checks the object against the ruleset and then corrects it in-place if necessary.
96
- """
97
- imp = await self.check_obj(obj, ruleset, **override_kwargs(kwargs, default=None))
98
- if imp is None:
99
- logger.warning(f"Censor failed for `{obj.__class__.__name__}`")
100
- return None
101
- if not imp:
102
- logger.info(f"No improvement found for `{obj.__class__.__name__}`.")
103
- return obj
104
- logger.info(f"Generated {len(imp)} improvement(s) for `{obj.__class__.__name__}")
105
- return await self.correct_obj_inplace(obj, improvement=Improvement.gather(*imp), **kwargs)
@@ -1,212 +0,0 @@
1
- """A class that provides the capability to check strings and objects against rules and guidelines."""
2
-
3
- from abc import ABC
4
- from asyncio import gather
5
- from typing import List, Optional, Unpack
6
-
7
- from fabricatio.capabilities.advanced_judge import AdvancedJudge
8
- from fabricatio.capabilities.propose import Propose
9
- from fabricatio.journal import logger
10
- from fabricatio.models.extra.patches import RuleSetMetadata
11
- from fabricatio.models.extra.problem import Improvement
12
- from fabricatio.models.extra.rule import Rule, RuleSet
13
- from fabricatio.models.generic import Display, WithBriefing
14
- from fabricatio.models.kwargs_types import ValidateKwargs
15
- from fabricatio.rust import CONFIG, TEMPLATE_MANAGER, detect_language
16
- from fabricatio.utils import override_kwargs
17
-
18
-
19
- class Check(AdvancedJudge, Propose, ABC):
20
- """Class for validating strings/objects against predefined rules and guidelines.
21
-
22
- This capability combines rule-based judgment and proposal generation to provide
23
- structured validation results with actionable improvement suggestions.
24
- """
25
-
26
- async def draft_ruleset(
27
- self, ruleset_requirement: str, rule_count: int = 0, **kwargs: Unpack[ValidateKwargs[Rule]]
28
- ) -> Optional[RuleSet]:
29
- """Generate rule set based on requirement description.
30
-
31
- Args:
32
- ruleset_requirement (str): Natural language description of desired ruleset characteristics
33
- rule_count (int): Number of rules to generate (0 for default count)
34
- **kwargs: Validation parameters for rule generation
35
-
36
- Returns:
37
- Optional[RuleSet]: Validated ruleset object or None if generation fails
38
-
39
- Notes:
40
- - Requires valid template configuration in configs.templates
41
- - Returns None if any step in rule generation fails
42
- - Uses `alist_str` for requirement breakdown and iterative rule proposal
43
- """
44
- rule_reqs = (
45
- await self.alist_str(
46
- TEMPLATE_MANAGER.render_template(
47
- CONFIG.templates.ruleset_requirement_breakdown_template,
48
- {"ruleset_requirement": ruleset_requirement},
49
- ),
50
- rule_count,
51
- **override_kwargs(kwargs, default=None),
52
- )
53
- if rule_count > 1
54
- else [ruleset_requirement]
55
- )
56
-
57
- if rule_reqs is None:
58
- return None
59
-
60
- rules = await self.propose(
61
- Rule,
62
- [
63
- TEMPLATE_MANAGER.render_template(CONFIG.templates.rule_requirement_template, {"rule_requirement": r})
64
- for r in rule_reqs
65
- ],
66
- **kwargs,
67
- )
68
- if any(r for r in rules if r is None):
69
- return None
70
-
71
- ruleset_patch = await self.propose(
72
- RuleSetMetadata,
73
- f"{ruleset_requirement}\n\nYou should use `{detect_language(ruleset_requirement)}`!",
74
- **override_kwargs(kwargs, default=None),
75
- )
76
-
77
- if ruleset_patch is None:
78
- return None
79
-
80
- return RuleSet(rules=rules, **ruleset_patch.as_kwargs())
81
-
82
- async def check_string_against_rule(
83
- self,
84
- input_text: str,
85
- rule: Rule,
86
- reference: str = "",
87
- **kwargs: Unpack[ValidateKwargs[Improvement]],
88
- ) -> Optional[Improvement]:
89
- """Validate text against specific rule.
90
-
91
- Args:
92
- input_text (str): Text content to validate
93
- rule (Rule): Rule instance for validation
94
- reference (str): Reference text for comparison (default: "")
95
- **kwargs: Configuration for validation process
96
-
97
- Returns:
98
- Optional[Improvement]: Suggested improvement if violation detected
99
-
100
- Notes:
101
- - Uses `evidently_judge` to determine violation presence
102
- - Renders template using `check_string_template` for proposal
103
- - Proposes Improvement only when violation is confirmed
104
- """
105
- if judge := await self.evidently_judge(
106
- f"# Content to exam\n{input_text}\n\n# Rule Must to follow\n{rule.display()}\nDoes `Content to exam` provided above violate the `{rule.name}` provided above?"
107
- f"should I take some measure to fix that violation? true for I do need, false for I don't need.",
108
- **override_kwargs(kwargs, default=None),
109
- ):
110
- logger.info(f"Rule `{rule.name}` violated: \n{judge.display()}")
111
- return await self.propose(
112
- Improvement,
113
- TEMPLATE_MANAGER.render_template(
114
- CONFIG.templates.check_string_template,
115
- {"to_check": input_text, "rule": rule.display(), "judge": judge.display(), "reference": reference},
116
- ),
117
- **kwargs,
118
- )
119
- return None
120
-
121
- async def check_obj_against_rule[M: (Display, WithBriefing)](
122
- self,
123
- obj: M,
124
- rule: Rule,
125
- reference: str = "",
126
- **kwargs: Unpack[ValidateKwargs[Improvement]],
127
- ) -> Optional[Improvement]:
128
- """Validate object against rule using text representation.
129
-
130
- Args:
131
- obj (M): Object implementing Display/WithBriefing interface
132
- rule (Rule): Validation rule
133
- reference (str): Reference text for comparison (default: "")
134
- **kwargs: Validation configuration parameters
135
-
136
- Returns:
137
- Optional[Improvement]: Improvement suggestion if issues found
138
-
139
- Notes:
140
- - Requires obj to implement display() or briefing property
141
- - Raises TypeError for incompatible object types
142
- - Converts object to text before string validation
143
- """
144
- if isinstance(obj, Display):
145
- input_text = obj.display()
146
- elif isinstance(obj, WithBriefing):
147
- input_text = obj.briefing
148
- else:
149
- raise TypeError("obj must be either Display or WithBriefing")
150
-
151
- return await self.check_string_against_rule(input_text, rule, reference, **kwargs)
152
-
153
- async def check_string(
154
- self,
155
- input_text: str,
156
- ruleset: RuleSet,
157
- reference: str = "",
158
- **kwargs: Unpack[ValidateKwargs[Improvement]],
159
- ) -> Optional[List[Improvement]]:
160
- """Validate text against full ruleset.
161
-
162
- Args:
163
- input_text (str): Text content to validate
164
- ruleset (RuleSet): Collection of validation rules
165
- reference (str): Reference text for comparison
166
- **kwargs: Validation configuration parameters
167
-
168
- Returns:
169
- Optional[Improvement]: First detected improvement
170
-
171
- Notes:
172
- - Checks rules sequentially and returns first violation
173
- - Halts validation after first successful improvement proposal
174
- - Maintains rule execution order from ruleset.rules list
175
- """
176
- imp_seq = await gather(
177
- *[self.check_string_against_rule(input_text, rule, reference, **kwargs) for rule in ruleset.rules]
178
- )
179
- if imp_seq is None:
180
- logger.warning(f"Generation failed for string check against `{ruleset.name}`")
181
- return None
182
- return [imp for imp in imp_seq if imp]
183
-
184
- async def check_obj[M: (Display, WithBriefing)](
185
- self,
186
- obj: M,
187
- ruleset: RuleSet,
188
- reference: str = "",
189
- **kwargs: Unpack[ValidateKwargs[Improvement]],
190
- ) -> Optional[List[Improvement]]:
191
- """Validate object against full ruleset.
192
-
193
- Args:
194
- obj (M): Object implementing Display/WithBriefing interface
195
- ruleset (RuleSet): Collection of validation rules
196
- reference (str): Reference text for comparison (default: "")
197
- **kwargs: Validation configuration parameters
198
-
199
- Returns:
200
- Optional[Improvement]: First detected improvement
201
-
202
- Notes:
203
- - Uses check_obj_against_rule for individual rule checks
204
- - Maintains same early termination behavior as check_string
205
- - Validates object through text conversion mechanism
206
- """
207
- imp_seq = await gather(*[self.check_obj_against_rule(obj, rule, reference, **kwargs) for rule in ruleset.rules])
208
-
209
- if imp_seq is None:
210
- logger.warning(f"Generation Failed for `{obj.__class__.__name__}` against Ruleset `{ruleset.name}`")
211
- return None
212
- return [i for i in imp_seq if i]