(no commit message)

This commit is contained in:
2025-10-29 20:23:58 -04:00
parent ce4d656800
commit 4d757a6394
3 changed files with 100 additions and 54 deletions

View File

@@ -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"]

View File

@@ -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
View File

@@ -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 docs 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__":