evolution-sdk 0.8.0__py3-none-any.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.
- evolution/__init__.py +102 -0
- evolution/adapters/__init__.py +28 -0
- evolution/adapters/base.py +21 -0
- evolution/adapters/crewai.py +86 -0
- evolution/adapters/direct.py +120 -0
- evolution/adapters/langchain.py +112 -0
- evolution/adapters/llamaindex.py +96 -0
- evolution/capture/__init__.py +22 -0
- evolution/capture/introspect.py +164 -0
- evolution/capture/recorder.py +109 -0
- evolution/capture/tracker.py +194 -0
- evolution/evaluators.py +268 -0
- evolution/exceptions.py +52 -0
- evolution/models/__init__.py +40 -0
- evolution/models/artifacts.py +248 -0
- evolution/models/evaluation.py +77 -0
- evolution/models/execution.py +77 -0
- evolution/models/manifest.py +210 -0
- evolution/repository.py +360 -0
- evolution/validator.py +55 -0
- evolution_sdk-0.8.0.dist-info/METADATA +240 -0
- evolution_sdk-0.8.0.dist-info/RECORD +25 -0
- evolution_sdk-0.8.0.dist-info/WHEEL +5 -0
- evolution_sdk-0.8.0.dist-info/licenses/LICENSE +21 -0
- evolution_sdk-0.8.0.dist-info/top_level.txt +1 -0
evolution/__init__.py
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Evolution Python SDK — AI-Native Version Control Platform.
|
|
3
|
+
"Version Intelligence, Not Code."
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from evolution.adapters import (
|
|
9
|
+
from_anthropic,
|
|
10
|
+
from_crewai,
|
|
11
|
+
from_langchain,
|
|
12
|
+
from_llamaindex,
|
|
13
|
+
from_openai,
|
|
14
|
+
)
|
|
15
|
+
from evolution.capture import RecordContextManager, record, track
|
|
16
|
+
from evolution.evaluators import (
|
|
17
|
+
DimensionScore,
|
|
18
|
+
EvaluationReport,
|
|
19
|
+
SemanticEvaluator,
|
|
20
|
+
)
|
|
21
|
+
from evolution.exceptions import (
|
|
22
|
+
ArtifactNotFoundError,
|
|
23
|
+
CommandExecutionError,
|
|
24
|
+
EvolutionError,
|
|
25
|
+
ManifestNotFoundError,
|
|
26
|
+
ManifestValidationError,
|
|
27
|
+
RepositoryAlreadyExistsError,
|
|
28
|
+
RepositoryNotFoundError,
|
|
29
|
+
)
|
|
30
|
+
from evolution.models import (
|
|
31
|
+
BaseArtifact,
|
|
32
|
+
EvaluationResult,
|
|
33
|
+
EvaluationScore,
|
|
34
|
+
Execution,
|
|
35
|
+
Manifest,
|
|
36
|
+
ManifestArtifacts,
|
|
37
|
+
MemoryArtifact,
|
|
38
|
+
ModelConfigArtifact,
|
|
39
|
+
PolicyArtifact,
|
|
40
|
+
PromptArtifact,
|
|
41
|
+
RetrievalArtifact,
|
|
42
|
+
TokenUsage,
|
|
43
|
+
ToolArtifact,
|
|
44
|
+
artifact_from_dict,
|
|
45
|
+
compute_blob_hash,
|
|
46
|
+
)
|
|
47
|
+
from evolution.repository import CommitInfo, RepoStatus, Repository
|
|
48
|
+
|
|
49
|
+
__version__ = "0.8.0"
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def init(path: Path | str = ".", name: str = "ai-intelligence") -> Repository:
|
|
53
|
+
"""Convenience function to initialize a new Evolution repository."""
|
|
54
|
+
return Repository.init(path=path, name=name)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def open(path: Path | str = ".") -> Repository:
|
|
58
|
+
"""Convenience function to open an existing Evolution repository."""
|
|
59
|
+
return Repository.open(path=path)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
__all__ = [
|
|
63
|
+
"ArtifactNotFoundError",
|
|
64
|
+
"BaseArtifact",
|
|
65
|
+
"CommandExecutionError",
|
|
66
|
+
"CommitInfo",
|
|
67
|
+
"DimensionScore",
|
|
68
|
+
"EvaluationReport",
|
|
69
|
+
"EvaluationResult",
|
|
70
|
+
"EvaluationScore",
|
|
71
|
+
"EvolutionError",
|
|
72
|
+
"Execution",
|
|
73
|
+
"Manifest",
|
|
74
|
+
"ManifestArtifacts",
|
|
75
|
+
"ManifestNotFoundError",
|
|
76
|
+
"ManifestValidationError",
|
|
77
|
+
"MemoryArtifact",
|
|
78
|
+
"ModelConfigArtifact",
|
|
79
|
+
"PolicyArtifact",
|
|
80
|
+
"PromptArtifact",
|
|
81
|
+
"RecordContextManager",
|
|
82
|
+
"RepoStatus",
|
|
83
|
+
"Repository",
|
|
84
|
+
"RepositoryAlreadyExistsError",
|
|
85
|
+
"RepositoryNotFoundError",
|
|
86
|
+
"RetrievalArtifact",
|
|
87
|
+
"SemanticEvaluator",
|
|
88
|
+
"TokenUsage",
|
|
89
|
+
"ToolArtifact",
|
|
90
|
+
"__version__",
|
|
91
|
+
"artifact_from_dict",
|
|
92
|
+
"compute_blob_hash",
|
|
93
|
+
"from_anthropic",
|
|
94
|
+
"from_crewai",
|
|
95
|
+
"from_langchain",
|
|
96
|
+
"from_llamaindex",
|
|
97
|
+
"from_openai",
|
|
98
|
+
"init",
|
|
99
|
+
"open",
|
|
100
|
+
"record",
|
|
101
|
+
"track",
|
|
102
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Evolution framework adapters package.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from evolution.adapters.base import BaseAdapter
|
|
6
|
+
from evolution.adapters.crewai import CrewAIAdapter, from_crewai
|
|
7
|
+
from evolution.adapters.direct import (
|
|
8
|
+
AnthropicAdapter,
|
|
9
|
+
OpenAIAdapter,
|
|
10
|
+
from_anthropic,
|
|
11
|
+
from_openai,
|
|
12
|
+
)
|
|
13
|
+
from evolution.adapters.langchain import LangChainAdapter, from_langchain
|
|
14
|
+
from evolution.adapters.llamaindex import LlamaIndexAdapter, from_llamaindex
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AnthropicAdapter",
|
|
18
|
+
"BaseAdapter",
|
|
19
|
+
"CrewAIAdapter",
|
|
20
|
+
"LangChainAdapter",
|
|
21
|
+
"LlamaIndexAdapter",
|
|
22
|
+
"OpenAIAdapter",
|
|
23
|
+
"from_anthropic",
|
|
24
|
+
"from_crewai",
|
|
25
|
+
"from_langchain",
|
|
26
|
+
"from_llamaindex",
|
|
27
|
+
"from_openai",
|
|
28
|
+
]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base protocol and abstract class for framework adapters.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from abc import ABC, abstractmethod
|
|
8
|
+
from typing import Any
|
|
9
|
+
|
|
10
|
+
from evolution.models.manifest import Manifest
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class BaseAdapter(ABC):
|
|
14
|
+
"""Abstract base class for converting framework-specific AI configurations
|
|
15
|
+
into standard Intelligence Manifests (Spec v1.0).
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
@abstractmethod
|
|
19
|
+
def to_manifest(self, obj: Any, name: str = "ai-intelligence", description: str = "") -> Manifest:
|
|
20
|
+
"""Converts a framework-specific object into an Evolution Manifest."""
|
|
21
|
+
pass
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CrewAI framework adapter for extracting multi-agent Intelligence Manifests.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from evolution.adapters.base import BaseAdapter
|
|
10
|
+
from evolution.models.artifacts import (
|
|
11
|
+
ModelConfigArtifact,
|
|
12
|
+
PromptArtifact,
|
|
13
|
+
ToolArtifact,
|
|
14
|
+
)
|
|
15
|
+
from evolution.models.manifest import Manifest
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CrewAIAdapter(BaseAdapter):
|
|
19
|
+
"""Converts CrewAI Crews, Agents, and Tasks into a multi-agent Intelligence Manifest."""
|
|
20
|
+
|
|
21
|
+
def to_manifest(self, obj: Any, name: str = "crewai-multi-agent", description: str = "") -> Manifest:
|
|
22
|
+
manifest = Manifest(name=name, description=description or "CrewAI multi-agent system state")
|
|
23
|
+
|
|
24
|
+
agents = getattr(obj, "agents", []) or []
|
|
25
|
+
if not agents and hasattr(obj, "role"): # If a single Agent was passed
|
|
26
|
+
agents = [obj]
|
|
27
|
+
|
|
28
|
+
seen_models = set()
|
|
29
|
+
seen_tools = set()
|
|
30
|
+
|
|
31
|
+
for idx, agent in enumerate(agents):
|
|
32
|
+
role = getattr(agent, "role", f"agent-{idx+1}")
|
|
33
|
+
goal = getattr(agent, "goal", "")
|
|
34
|
+
backstory = getattr(agent, "backstory", "")
|
|
35
|
+
|
|
36
|
+
# 1. Agent role prompt artifact
|
|
37
|
+
prompt_content = f"Role: {role}\nGoal: {goal}\nBackstory: {backstory}".strip()
|
|
38
|
+
manifest.add_artifact(PromptArtifact(
|
|
39
|
+
name=f"{role.lower().replace(' ', '-')}-prompt",
|
|
40
|
+
role="system",
|
|
41
|
+
description=prompt_content[:300],
|
|
42
|
+
))
|
|
43
|
+
|
|
44
|
+
# 2. Agent tools
|
|
45
|
+
agent_tools = getattr(agent, "tools", []) or []
|
|
46
|
+
for t in agent_tools:
|
|
47
|
+
t_name = getattr(t, "name", str(t))
|
|
48
|
+
if t_name not in seen_tools:
|
|
49
|
+
seen_tools.add(t_name)
|
|
50
|
+
manifest.add_artifact(ToolArtifact(
|
|
51
|
+
name=t_name,
|
|
52
|
+
provider="crewai",
|
|
53
|
+
description=getattr(t, "description", ""),
|
|
54
|
+
))
|
|
55
|
+
|
|
56
|
+
# 3. Agent LLM
|
|
57
|
+
llm = getattr(agent, "llm", None)
|
|
58
|
+
if llm is not None and str(llm) not in seen_models:
|
|
59
|
+
seen_models.add(str(llm))
|
|
60
|
+
model_str = getattr(llm, "model", getattr(llm, "model_name", str(llm)))
|
|
61
|
+
provider = "openai"
|
|
62
|
+
if "claude" in str(model_str).lower():
|
|
63
|
+
provider = "anthropic"
|
|
64
|
+
elif "gemini" in str(model_str).lower():
|
|
65
|
+
provider = "google"
|
|
66
|
+
|
|
67
|
+
manifest.add_artifact(ModelConfigArtifact(
|
|
68
|
+
name=f"model-{role.lower().replace(' ', '-')}",
|
|
69
|
+
model=str(model_str),
|
|
70
|
+
provider=provider,
|
|
71
|
+
))
|
|
72
|
+
|
|
73
|
+
# Capture crew structure in metadata
|
|
74
|
+
tasks = getattr(obj, "tasks", []) or []
|
|
75
|
+
manifest.metadata["crewai"] = {
|
|
76
|
+
"agent_count": len(agents),
|
|
77
|
+
"task_count": len(tasks),
|
|
78
|
+
"process": str(getattr(obj, "process", "sequential")),
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return manifest
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def from_crewai(obj: Any, name: str = "crewai-multi-agent", description: str = "") -> Manifest:
|
|
85
|
+
"""Convenience function to extract an Intelligence Manifest from a CrewAI Crew or Agent."""
|
|
86
|
+
return CrewAIAdapter().to_manifest(obj, name=name, description=description)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Direct API adapters for OpenAI and Anthropic API payloads and clients.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from evolution.adapters.base import BaseAdapter
|
|
10
|
+
from evolution.models.artifacts import (
|
|
11
|
+
ModelConfigArtifact,
|
|
12
|
+
PromptArtifact,
|
|
13
|
+
ToolArtifact,
|
|
14
|
+
)
|
|
15
|
+
from evolution.models.manifest import Manifest
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class OpenAIAdapter(BaseAdapter):
|
|
19
|
+
"""Converts OpenAI request dictionaries or client configurations into an Intelligence Manifest."""
|
|
20
|
+
|
|
21
|
+
def to_manifest(self, obj: Any, name: str = "openai-system", description: str = "") -> Manifest:
|
|
22
|
+
manifest = Manifest(name=name, description=description or "OpenAI API intelligence state")
|
|
23
|
+
params = obj if isinstance(obj, dict) else getattr(obj, "__dict__", {})
|
|
24
|
+
|
|
25
|
+
# 1. Model configuration
|
|
26
|
+
model = params.get("model", "gpt-4o")
|
|
27
|
+
temp = params.get("temperature", 0.7)
|
|
28
|
+
max_tokens = params.get("max_tokens") or params.get("max_completion_tokens")
|
|
29
|
+
top_p = params.get("top_p")
|
|
30
|
+
|
|
31
|
+
manifest.add_artifact(ModelConfigArtifact(
|
|
32
|
+
name=f"openai-{model}",
|
|
33
|
+
model=str(model),
|
|
34
|
+
provider="openai",
|
|
35
|
+
temperature=float(temp) if temp is not None else 0.7,
|
|
36
|
+
max_tokens=int(max_tokens) if max_tokens is not None else None,
|
|
37
|
+
top_p=float(top_p) if top_p is not None else None,
|
|
38
|
+
))
|
|
39
|
+
|
|
40
|
+
# 2. Prompts from messages
|
|
41
|
+
messages = params.get("messages", [])
|
|
42
|
+
for idx, msg in enumerate(messages):
|
|
43
|
+
if isinstance(msg, dict):
|
|
44
|
+
role = msg.get("role", "user")
|
|
45
|
+
content = str(msg.get("content", ""))
|
|
46
|
+
if role in ("system", "user", "assistant", "few_shot"):
|
|
47
|
+
manifest.add_artifact(PromptArtifact(
|
|
48
|
+
name=f"openai-msg-{idx+1}-{role}",
|
|
49
|
+
role=role,
|
|
50
|
+
description=content[:200],
|
|
51
|
+
))
|
|
52
|
+
|
|
53
|
+
# 3. Tools
|
|
54
|
+
tools = params.get("tools", [])
|
|
55
|
+
for t in tools:
|
|
56
|
+
if isinstance(t, dict):
|
|
57
|
+
fn = t.get("function", {})
|
|
58
|
+
t_name = fn.get("name") or t.get("name", "custom-tool")
|
|
59
|
+
t_desc = fn.get("description", "")
|
|
60
|
+
manifest.add_artifact(ToolArtifact(
|
|
61
|
+
name=t_name,
|
|
62
|
+
provider="openai",
|
|
63
|
+
description=t_desc,
|
|
64
|
+
))
|
|
65
|
+
|
|
66
|
+
return manifest
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class AnthropicAdapter(BaseAdapter):
|
|
70
|
+
"""Converts Anthropic request dictionaries or client configurations into an Intelligence Manifest."""
|
|
71
|
+
|
|
72
|
+
def to_manifest(self, obj: Any, name: str = "anthropic-system", description: str = "") -> Manifest:
|
|
73
|
+
manifest = Manifest(name=name, description=description or "Anthropic API intelligence state")
|
|
74
|
+
params = obj if isinstance(obj, dict) else getattr(obj, "__dict__", {})
|
|
75
|
+
|
|
76
|
+
# 1. Model configuration
|
|
77
|
+
model = params.get("model", "claude-3.5-sonnet")
|
|
78
|
+
temp = params.get("temperature", 0.7)
|
|
79
|
+
max_tokens = params.get("max_tokens", 4096)
|
|
80
|
+
|
|
81
|
+
manifest.add_artifact(ModelConfigArtifact(
|
|
82
|
+
name=f"anthropic-{model}",
|
|
83
|
+
model=str(model),
|
|
84
|
+
provider="anthropic",
|
|
85
|
+
temperature=float(temp) if temp is not None else 0.7,
|
|
86
|
+
max_tokens=int(max_tokens) if max_tokens is not None else None,
|
|
87
|
+
))
|
|
88
|
+
|
|
89
|
+
# 2. System prompt
|
|
90
|
+
system = params.get("system")
|
|
91
|
+
if system:
|
|
92
|
+
manifest.add_artifact(PromptArtifact(
|
|
93
|
+
name="anthropic-system-prompt",
|
|
94
|
+
role="system",
|
|
95
|
+
description=str(system)[:200],
|
|
96
|
+
))
|
|
97
|
+
|
|
98
|
+
# 3. Tools
|
|
99
|
+
tools = params.get("tools", [])
|
|
100
|
+
for t in tools:
|
|
101
|
+
if isinstance(t, dict):
|
|
102
|
+
t_name = t.get("name", "custom-tool")
|
|
103
|
+
t_desc = t.get("description", "")
|
|
104
|
+
manifest.add_artifact(ToolArtifact(
|
|
105
|
+
name=t_name,
|
|
106
|
+
provider="anthropic",
|
|
107
|
+
description=t_desc,
|
|
108
|
+
))
|
|
109
|
+
|
|
110
|
+
return manifest
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def from_openai(params: dict[str, Any] | Any, name: str = "openai-system", description: str = "") -> Manifest:
|
|
114
|
+
"""Convenience function to extract an Intelligence Manifest from an OpenAI request payload."""
|
|
115
|
+
return OpenAIAdapter().to_manifest(params, name=name, description=description)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def from_anthropic(params: dict[str, Any] | Any, name: str = "anthropic-system", description: str = "") -> Manifest:
|
|
119
|
+
"""Convenience function to extract an Intelligence Manifest from an Anthropic request payload."""
|
|
120
|
+
return AnthropicAdapter().to_manifest(params, name=name, description=description)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LangChain framework adapter for extracting Intelligence Manifests.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from evolution.adapters.base import BaseAdapter
|
|
10
|
+
from evolution.models.artifacts import (
|
|
11
|
+
MemoryArtifact,
|
|
12
|
+
ModelConfigArtifact,
|
|
13
|
+
PromptArtifact,
|
|
14
|
+
ToolArtifact,
|
|
15
|
+
)
|
|
16
|
+
from evolution.models.manifest import Manifest
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class LangChainAdapter(BaseAdapter):
|
|
20
|
+
"""Converts LangChain chains, agents, prompt templates, and tools into an Intelligence Manifest."""
|
|
21
|
+
|
|
22
|
+
def to_manifest(self, obj: Any, name: str = "langchain-agent", description: str = "") -> Manifest:
|
|
23
|
+
manifest = Manifest(name=name, description=description or "LangChain application state")
|
|
24
|
+
|
|
25
|
+
# 1. Inspect LLM / Model
|
|
26
|
+
llm = getattr(obj, "llm", None) or getattr(obj, "llm_chain", None)
|
|
27
|
+
if llm is None and (hasattr(obj, "model_name") or hasattr(obj, "model")):
|
|
28
|
+
llm = obj
|
|
29
|
+
|
|
30
|
+
if llm is not None:
|
|
31
|
+
model_name = getattr(llm, "model_name", None) or getattr(llm, "model", "gpt-4o")
|
|
32
|
+
temperature = getattr(llm, "temperature", 0.7)
|
|
33
|
+
max_tokens = getattr(llm, "max_tokens", None) or getattr(llm, "max_output_tokens", None)
|
|
34
|
+
|
|
35
|
+
# Determine provider
|
|
36
|
+
provider = "openai"
|
|
37
|
+
cls_name = llm.__class__.__name__.lower()
|
|
38
|
+
if "anthropic" in cls_name or "claude" in str(model_name).lower():
|
|
39
|
+
provider = "anthropic"
|
|
40
|
+
elif "google" in cls_name or "gemini" in str(model_name).lower():
|
|
41
|
+
provider = "google"
|
|
42
|
+
elif "mistral" in cls_name:
|
|
43
|
+
provider = "mistral"
|
|
44
|
+
elif "cohere" in cls_name:
|
|
45
|
+
provider = "cohere"
|
|
46
|
+
|
|
47
|
+
manifest.add_artifact(ModelConfigArtifact(
|
|
48
|
+
name="langchain-llm",
|
|
49
|
+
model=str(model_name),
|
|
50
|
+
provider=provider,
|
|
51
|
+
temperature=float(temperature) if temperature is not None else 0.7,
|
|
52
|
+
max_tokens=int(max_tokens) if max_tokens is not None else None,
|
|
53
|
+
))
|
|
54
|
+
|
|
55
|
+
# 2. Inspect Prompts
|
|
56
|
+
prompt = getattr(obj, "prompt", None) or getattr(obj, "prompt_template", None)
|
|
57
|
+
if prompt is None and hasattr(obj, "messages"):
|
|
58
|
+
prompt = obj
|
|
59
|
+
|
|
60
|
+
if prompt is not None:
|
|
61
|
+
prompt_text = ""
|
|
62
|
+
if hasattr(prompt, "template"):
|
|
63
|
+
prompt_text = str(prompt.template)
|
|
64
|
+
elif hasattr(prompt, "messages"):
|
|
65
|
+
msg_strs = []
|
|
66
|
+
for m in prompt.messages:
|
|
67
|
+
role = getattr(m, "role", "system")
|
|
68
|
+
content = getattr(m, "content", getattr(m, "template", str(m)))
|
|
69
|
+
msg_strs.append(f"[{role}] {content}")
|
|
70
|
+
prompt_text = "\n".join(msg_strs)
|
|
71
|
+
else:
|
|
72
|
+
prompt_text = str(prompt)
|
|
73
|
+
|
|
74
|
+
manifest.add_artifact(PromptArtifact(
|
|
75
|
+
name="langchain-prompt",
|
|
76
|
+
role="system",
|
|
77
|
+
description=prompt_text[:200] if prompt_text else "LangChain prompt template",
|
|
78
|
+
))
|
|
79
|
+
|
|
80
|
+
# 3. Inspect Tools
|
|
81
|
+
tools = getattr(obj, "tools", []) or []
|
|
82
|
+
for t in tools:
|
|
83
|
+
tool_name = getattr(t, "name", str(t))
|
|
84
|
+
tool_desc = getattr(t, "description", "")
|
|
85
|
+
manifest.add_artifact(ToolArtifact(
|
|
86
|
+
name=tool_name,
|
|
87
|
+
provider="langchain",
|
|
88
|
+
description=tool_desc,
|
|
89
|
+
))
|
|
90
|
+
|
|
91
|
+
# 4. Inspect Memory
|
|
92
|
+
memory = getattr(obj, "memory", None)
|
|
93
|
+
if memory is not None:
|
|
94
|
+
mem_cls = memory.__class__.__name__.lower()
|
|
95
|
+
strategy = "buffer_window"
|
|
96
|
+
if "summary" in mem_cls:
|
|
97
|
+
strategy = "summary"
|
|
98
|
+
elif "vector" in mem_cls:
|
|
99
|
+
strategy = "vector"
|
|
100
|
+
|
|
101
|
+
manifest.add_artifact(MemoryArtifact(
|
|
102
|
+
name="langchain-memory",
|
|
103
|
+
strategy=strategy,
|
|
104
|
+
max_tokens=getattr(memory, "max_token_limit", None),
|
|
105
|
+
))
|
|
106
|
+
|
|
107
|
+
return manifest
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def from_langchain(obj: Any, name: str = "langchain-agent", description: str = "") -> Manifest:
|
|
111
|
+
"""Convenience function to extract an Intelligence Manifest from a LangChain object."""
|
|
112
|
+
return LangChainAdapter().to_manifest(obj, name=name, description=description)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""
|
|
2
|
+
LlamaIndex framework adapter for extracting Intelligence Manifests.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from evolution.adapters.base import BaseAdapter
|
|
10
|
+
from evolution.models.artifacts import (
|
|
11
|
+
ModelConfigArtifact,
|
|
12
|
+
RetrievalArtifact,
|
|
13
|
+
)
|
|
14
|
+
from evolution.models.manifest import Manifest
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class LlamaIndexAdapter(BaseAdapter):
|
|
18
|
+
"""Converts LlamaIndex indices, query engines, and retrievers into an Intelligence Manifest."""
|
|
19
|
+
|
|
20
|
+
def to_manifest(self, obj: Any, name: str = "llamaindex-rag", description: str = "") -> Manifest:
|
|
21
|
+
manifest = Manifest(name=name, description=description or "LlamaIndex RAG application state")
|
|
22
|
+
|
|
23
|
+
# 1. Extract Retrieval settings
|
|
24
|
+
source = "chroma"
|
|
25
|
+
chunk_size: int | None = None
|
|
26
|
+
top_k: int | None = None
|
|
27
|
+
|
|
28
|
+
# Inspect storage_context / vector_store
|
|
29
|
+
sc = getattr(obj, "storage_context", None)
|
|
30
|
+
vs = getattr(sc, "vector_store", None) if sc else getattr(obj, "vector_store", None)
|
|
31
|
+
if vs is not None:
|
|
32
|
+
vs_name = vs.__class__.__name__.lower()
|
|
33
|
+
if "pinecone" in vs_name:
|
|
34
|
+
source = "pinecone"
|
|
35
|
+
elif "weaviate" in vs_name:
|
|
36
|
+
source = "weaviate"
|
|
37
|
+
elif "elasticsearch" in vs_name or "elastic" in vs_name:
|
|
38
|
+
source = "elasticsearch"
|
|
39
|
+
elif "chroma" in vs_name:
|
|
40
|
+
source = "chroma"
|
|
41
|
+
else:
|
|
42
|
+
source = "local"
|
|
43
|
+
|
|
44
|
+
# Inspect retriever / query engine top_k
|
|
45
|
+
retriever = getattr(obj, "retriever", None) or getattr(obj, "_retriever", None)
|
|
46
|
+
if retriever is not None:
|
|
47
|
+
top_k = getattr(retriever, "similarity_top_k", None) or getattr(retriever, "top_k", None)
|
|
48
|
+
elif hasattr(obj, "similarity_top_k"):
|
|
49
|
+
top_k = getattr(obj, "similarity_top_k")
|
|
50
|
+
|
|
51
|
+
# Inspect chunk size
|
|
52
|
+
service_context = getattr(obj, "service_context", None)
|
|
53
|
+
if service_context is not None:
|
|
54
|
+
node_parser = getattr(service_context, "node_parser", None)
|
|
55
|
+
if node_parser is not None:
|
|
56
|
+
chunk_size = getattr(node_parser, "chunk_size", None)
|
|
57
|
+
elif hasattr(obj, "chunk_size"):
|
|
58
|
+
chunk_size = getattr(obj, "chunk_size")
|
|
59
|
+
|
|
60
|
+
manifest.add_artifact(RetrievalArtifact(
|
|
61
|
+
name="llamaindex-retrieval",
|
|
62
|
+
source=source,
|
|
63
|
+
chunk_size=int(chunk_size) if chunk_size is not None else 512,
|
|
64
|
+
top_k=int(top_k) if top_k is not None else 5,
|
|
65
|
+
description="LlamaIndex vector retrieval configuration",
|
|
66
|
+
))
|
|
67
|
+
|
|
68
|
+
# 2. Extract LLM configuration
|
|
69
|
+
llm = getattr(obj, "llm", None)
|
|
70
|
+
if service_context and not llm:
|
|
71
|
+
llm = getattr(service_context, "llm", None)
|
|
72
|
+
|
|
73
|
+
if llm is not None:
|
|
74
|
+
model_name = getattr(llm, "model", getattr(llm, "model_name", "gpt-4o"))
|
|
75
|
+
temperature = getattr(llm, "temperature", 0.1)
|
|
76
|
+
|
|
77
|
+
provider = "openai"
|
|
78
|
+
cls_name = llm.__class__.__name__.lower()
|
|
79
|
+
if "anthropic" in cls_name or "claude" in str(model_name).lower():
|
|
80
|
+
provider = "anthropic"
|
|
81
|
+
elif "google" in cls_name or "gemini" in str(model_name).lower():
|
|
82
|
+
provider = "google"
|
|
83
|
+
|
|
84
|
+
manifest.add_artifact(ModelConfigArtifact(
|
|
85
|
+
name="llamaindex-llm",
|
|
86
|
+
model=str(model_name),
|
|
87
|
+
provider=provider,
|
|
88
|
+
temperature=float(temperature) if temperature is not None else 0.1,
|
|
89
|
+
))
|
|
90
|
+
|
|
91
|
+
return manifest
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def from_llamaindex(obj: Any, name: str = "llamaindex-rag", description: str = "") -> Manifest:
|
|
95
|
+
"""Convenience function to extract an Intelligence Manifest from a LlamaIndex object."""
|
|
96
|
+
return LlamaIndexAdapter().to_manifest(obj, name=name, description=description)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Automatic intelligence capture and execution recording package.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from evolution.capture.introspect import (
|
|
6
|
+
extract_docstring_prompt,
|
|
7
|
+
extract_inputs_from_args,
|
|
8
|
+
extract_llm_response,
|
|
9
|
+
extract_model_config_from_kwargs,
|
|
10
|
+
)
|
|
11
|
+
from evolution.capture.recorder import RecordContextManager, record
|
|
12
|
+
from evolution.capture.tracker import track
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"RecordContextManager",
|
|
16
|
+
"extract_docstring_prompt",
|
|
17
|
+
"extract_inputs_from_args",
|
|
18
|
+
"extract_llm_response",
|
|
19
|
+
"extract_model_config_from_kwargs",
|
|
20
|
+
"record",
|
|
21
|
+
"track",
|
|
22
|
+
]
|