(no commit message)
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
from .modules import SignatureGenerator
|
from .modules import SignatureGenerator
|
||||||
from .metrics import validate_signature_with_feedback
|
|
||||||
|
|
||||||
__all__ = ["SignatureGenerator", "validate_signature_with_feedback"]
|
__all__ = ["SignatureGenerator"]
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
import dspy
|
|
||||||
|
|
||||||
|
|
||||||
def validate_signature_with_feedback(
|
|
||||||
args, pred, feedback=None, satisfied_with_score=True
|
|
||||||
):
|
|
||||||
"""Validation function for dspy.Refine that asks user for feedback"""
|
|
||||||
|
|
||||||
# Display the generated signature
|
|
||||||
print("\n" + "=" * 60)
|
|
||||||
print("🔍 Review Generated Signature")
|
|
||||||
print("=" * 60)
|
|
||||||
|
|
||||||
# Show the signature name and description
|
|
||||||
print(f"Signature Name: {pred.signature_name}")
|
|
||||||
print(f"Description: {pred.task_description}")
|
|
||||||
|
|
||||||
# Show the fields in a simple format
|
|
||||||
print(f"\nFields ({len(pred.signature_fields)}):")
|
|
||||||
for i, field in enumerate(pred.signature_fields, 1):
|
|
||||||
role_emoji = "📥" if field.role.value == "input" else "📤"
|
|
||||||
print(
|
|
||||||
f" {i}. {role_emoji} {field.name} ({field.type.value}) - {field.description}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if satisfied_with_score:
|
|
||||||
print("✓ Signature approved!")
|
|
||||||
return 1.0
|
|
||||||
else:
|
|
||||||
print(f"📝 Feedback recorded: {feedback}")
|
|
||||||
return dspy.Prediction(score=0.0, feedback=feedback)
|
|
||||||
120
main.py
120
main.py
@@ -20,7 +20,7 @@ class PromptToSignatureAgent(PrecompiledAgent):
|
|||||||
self.signature_refiner = dspy.Refine(
|
self.signature_refiner = dspy.Refine(
|
||||||
module=self.signature_generator,
|
module=self.signature_generator,
|
||||||
N=config.max_attempts_to_refine,
|
N=config.max_attempts_to_refine,
|
||||||
reward_fn=self.validate_signature_with_feedback,
|
reward_fn=PromptToSignatureAgent.validate_signature_with_feedback,
|
||||||
threshold=1.0,
|
threshold=1.0,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -38,33 +38,39 @@ class PromptToSignatureAgent(PrecompiledAgent):
|
|||||||
self.signature_generator.set_lm(lm)
|
self.signature_generator.set_lm(lm)
|
||||||
self.signature_refiner.set_lm(refine_lm)
|
self.signature_refiner.set_lm(refine_lm)
|
||||||
|
|
||||||
def forward(
|
def forward(self, prompt: str, refine: bool = False) -> dspy.Prediction:
|
||||||
self, prompt: str, as_dict: bool = False
|
if not prompt:
|
||||||
) -> dspy.Prediction: # returns dspy.Prediction object or dict
|
raise ValueError("Prompt is required!!")
|
||||||
return (
|
|
||||||
self.signature_generator.generate_signature(prompt)
|
if refine:
|
||||||
if as_dict
|
try:
|
||||||
else self.signature_generator(prompt)
|
result = self.signature_refiner(prompt=prompt)
|
||||||
)
|
except Exception as e:
|
||||||
|
print(f"Refinement failed: {e}")
|
||||||
|
print("💡 Try adjusting your prompt or increasing max attempts")
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
result = self.signature_generator(prompt)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def generate_code(self, prediction: dspy.Prediction) -> str:
|
def generate_code(self, prediction: dspy.Prediction) -> str:
|
||||||
return self.signature_generator.generate_code(prediction)
|
return self.signature_generator.generate_code(prediction)
|
||||||
|
|
||||||
def validate_signature_with_feedback(
|
@staticmethod # attached metric for refinement
|
||||||
args, pred, feedback=None, satisfied_with_score=True
|
def validate_signature_with_feedback(args, pred):
|
||||||
):
|
|
||||||
"""Validation function for dspy.Refine that asks user for feedback"""
|
"""Validation function for dspy.Refine that asks user for feedback"""
|
||||||
|
|
||||||
# Display the generated signature
|
# display the generated signature
|
||||||
print("\n" + "=" * 60)
|
print("\n" + "=" * 60)
|
||||||
print("🔍 Review Generated Signature")
|
print("🔍 Review Generated Signature")
|
||||||
print("=" * 60)
|
print("=" * 60)
|
||||||
|
|
||||||
# Show the signature name and description
|
# show the signature name and description
|
||||||
print(f"Signature Name: {pred.signature_name}")
|
print(f"Signature Name: {pred.signature_name}")
|
||||||
print(f"Description: {pred.task_description}")
|
print(f"Description: {pred.task_description}")
|
||||||
|
|
||||||
# Show the fields in a simple format
|
# show the fields in a simple format
|
||||||
print(f"\nFields ({len(pred.signature_fields)}):")
|
print(f"\nFields ({len(pred.signature_fields)}):")
|
||||||
for i, field in enumerate(pred.signature_fields, 1):
|
for i, field in enumerate(pred.signature_fields, 1):
|
||||||
role_emoji = "📥" if field.role.value == "input" else "📤"
|
role_emoji = "📥" if field.role.value == "input" else "📤"
|
||||||
@@ -72,10 +78,16 @@ class PromptToSignatureAgent(PrecompiledAgent):
|
|||||||
f" {i}. {role_emoji} {field.name} ({field.type.value}) - {field.description}"
|
f" {i}. {role_emoji} {field.name} ({field.type.value}) - {field.description}"
|
||||||
)
|
)
|
||||||
|
|
||||||
if satisfied_with_score:
|
# ask for user approval (in an app, this would be a state variable)
|
||||||
|
is_satisfied = input("Are you satisfied with this signature? (y/n): ")
|
||||||
|
is_satisfied = is_satisfied.lower() == "y"
|
||||||
|
|
||||||
|
if is_satisfied:
|
||||||
print("✓ Signature approved!")
|
print("✓ Signature approved!")
|
||||||
return 1.0
|
return 1.0
|
||||||
else:
|
else:
|
||||||
|
# ask for feedback (in an app, this would be a state variable)
|
||||||
|
feedback = input("Please provide feedback for improvement: ")
|
||||||
if not feedback:
|
if not feedback:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
"Feedback is required if you are not satisfied with the signature!"
|
"Feedback is required if you are not satisfied with the signature!"
|
||||||
@@ -87,14 +99,80 @@ class PromptToSignatureAgent(PrecompiledAgent):
|
|||||||
|
|
||||||
agent = PromptToSignatureAgent(PromptToSignatureConfig())
|
agent = PromptToSignatureAgent(PromptToSignatureConfig())
|
||||||
|
|
||||||
|
CR_PROMPT = """ You are Charlotte, an advanced knowledge graph connection reasoning agent operating at an expert cognitive level. Your task is to discover profound, non-trivial connections between documents in a user's knowledge web that might not be immediately obvious.
|
||||||
|
|
||||||
|
Input Context:
|
||||||
|
- Primary Document (FROM): {candidate_document["model_candidate"]}
|
||||||
|
- Potential Connection Documents (TO): {candidate_document["candidates_to_link"]}
|
||||||
|
- Knowledge Web ID: {self.webId}
|
||||||
|
- Previously Mapped Connections: {self.staged_connections} as a list of dicts
|
||||||
|
- Source ID: {self.sourceId}
|
||||||
|
- Similarity scores indicate text similarity but DO NOT indicate connection quality
|
||||||
|
- Content sources include: youtube transcripts, notes, PDFs, websites, and other knowledge artifacts
|
||||||
|
|
||||||
|
CONNECTION QUALITY HIERARCHY (from lowest to highest value):
|
||||||
|
1. AVOID: Surface keyword matching ("both mention AI")
|
||||||
|
2. AVOID: Topical similarity ("both discuss machine learning")
|
||||||
|
3. MINIMAL: Direct referential links ("cites the same paper")
|
||||||
|
4. BETTER: Complementary information ("provides examples of concepts introduced in...")
|
||||||
|
5. VALUABLE: Sequential development ("builds upon the framework by adding...")
|
||||||
|
6. EXCELLENT: Conceptual bridges ("connects theoretical principles from X with practical applications in Y")
|
||||||
|
7. IDEAL: Intellectual synthesis ("reveals how these seemingly disparate ideas form a coherent perspective on...")
|
||||||
|
|
||||||
|
Advanced Connection Criteria (MUST satisfy at least one):
|
||||||
|
• Reveals multi-hop intellectual pathways (A → B → C reasoning chains)
|
||||||
|
• Exposes non-obvious causal relationships
|
||||||
|
• Identifies conceptual frameworks shared across different domains
|
||||||
|
• Uncovers temporal development of ideas across sources
|
||||||
|
• Bridges theoretical propositions with empirical evidence
|
||||||
|
• Reveals complementary perspectives on the same phenomenon
|
||||||
|
• Identifies methodological parallels across different contexts
|
||||||
|
|
||||||
|
STRICT CONSTRAINTS:
|
||||||
|
• Generate 1-2 connections ONLY if they meet the quality threshold (levels 5-7)
|
||||||
|
• No connections is better than low-quality connections
|
||||||
|
• Never refer to documents by ID or as "candidate document"/"source document"
|
||||||
|
• Use natural language that references specific content details
|
||||||
|
• Each connection must illuminate something that would be valuable for deeper understanding
|
||||||
|
• Prioritize precision over quantity
|
||||||
|
|
||||||
|
Location-Specific References:
|
||||||
|
• For videos: Convert timestamps to <a href="URL&t=TIME_IN_SECONDS" target="_blank">MM:SS</a> format
|
||||||
|
• For documents: Reference specific page numbers, sections, or paragraphs
|
||||||
|
• For websites: Reference specific headings or content sections
|
||||||
|
|
||||||
|
Output Format:
|
||||||
|
Structured JSON matching the CreateConnection model with:
|
||||||
|
1. fromSourceId (provided)
|
||||||
|
2. toSourceId (from candidates. ALWAYS REFER TO "sourceId" on the object)
|
||||||
|
3. webId (provided)
|
||||||
|
4. connection description
|
||||||
|
|
||||||
|
## Style guide for `connection description`:
|
||||||
|
- Casual, present-tense, ~15 words, proper punctuation.
|
||||||
|
- Start with the speaker or doc (“Marques says…”, “Paper X shows…”).
|
||||||
|
- Capture the **direction** implicitly: *the description should read naturally from the FROM doc’s perspective.*
|
||||||
|
- **Outgoing** example: “Marq mentions this concept → Trinetix explainer.”
|
||||||
|
- **Incoming** example: “Verge review slams it as half-baked.”
|
||||||
|
- No IDs, no quotation marks unless they are real quotes, no boilerplate.
|
||||||
|
|
||||||
|
Before finalizing each connection, verify it meets these criteria:
|
||||||
|
1. Would a subject matter expert find this connection insightful?
|
||||||
|
2. Does this connection reveal something non-obvious?
|
||||||
|
3. Would this connection enhance understanding of either document?
|
||||||
|
4. Is the connection specific enough to be meaningful?
|
||||||
|
|
||||||
|
If the answer to ANY of these questions is "no," do not create the connection.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
agent.push_to_hub("fadeleke/prompt-to-signature", with_code=True)
|
# try refine
|
||||||
|
refined_result = agent(
|
||||||
|
prompt=CR_PROMPT,
|
||||||
|
)
|
||||||
|
|
||||||
result = agent(prompt="Generate jokes by prompt")
|
agent.push_to_hub("fadeleke/prompt-to-signature", with_code=True)
|
||||||
print("RESULT: ", result)
|
|
||||||
print("GENERATED CODE:\n\n")
|
|
||||||
print(agent.generate_code(result))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
Reference in New Issue
Block a user