← all conversations

DeerFlow Persona Engine

2026-03-252 turns13,491 charsgpt-5-3
document-querypersona-enginetext-generation

Summary

User is building a DeerFlow persona query engine to retrieve documents and generate responses in specific or blended persona voices.

Messages

rewrite: # DeerFlow Persona Query Engine Query your document bank and get responses in specific personas' voices. Blend personas to create hybrid voices. Built for Daniel's 4,865-document DeerFlow bank. ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Persona Query Engine │ ├─────────────────────────────────────────────────────────────┤ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ FastAPI │ │ Streamlit │ │ Python Client │ │ │ │ Server │ │ UI │ │ │ │ │ └──────┬───────┘ └──────────────┘ └──────────────────┘ │ │ │ │ │ ┌──────▼───────┐ │ │ │ Query │ │ │ │ Engine │ │ │ └──────┬───────┘ │ │ │ │ │ ┌──────▼─────────────────────────────────┐ │ │ │ DeerFlow Bank (4,865 docs) │ │ │ │ - documents/ │ │ │ │ - metadata/index.json │ │ │ │ - vectors/ │ │ │ └────────────────────────────────────────┘ │ │ │ │ │ ┌──────▼───────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ Persona │ │ Persona │ │ Style │ │ │ │ Extractor │ │ Blender │ │ Engine │ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ │ │ │ │ ┌──────▼───────┐ │ │ │ Ollama │ (llama3.2 or gemma-3) │ │ └──────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ## Quick Start ### 1. Install dependencies ```bash pip install fastapi uvicorn ollama streamlit requests pydantic ``` ### 2. Start the API server ```bash python persona_api.py ``` Server runs on `http://localhost:8000` ### 3. Start the UI (optional) ```bash streamlit run persona_ui.py ``` UI runs on `http://localhost:8501` ### 4. Query via API ```bash # Query in KonradFreeman's voice curl -X POST http://localhost:8000/query \ -H "Content-Type: application/json" \ -d '{ "query": "What do you think about local-first AI?", "persona": "KonradFreeman" }' # Blend personas curl -X POST http://localhost:8000/query \ -H "Content-Type: application/json" \ -d '{ "query": "How should I approach building an AI startup?", "blended_persona": [ {"KonradFreeman": 0.7}, {"Daniel": 0.3} ] }' ``` ## API Endpoints ### POST /query Query the bank with persona styling. **Request:** ```json { "query": "string", "persona": "string (optional)", "blended_persona": [{"author": weight}, ...], "search_mode": "hybrid|keyword|author" } ``` **Response:** ```json { "success": true, "query": "original query", "persona_used": "KonradFreeman", "documents_found": 12, "content": "Styled response...", "source_documents": ["id1", "id2"], "persona_json": {...} } ``` ### POST /extract Extract a persona from an author's documents. ```json { "author": "KonradFreeman" } ``` ### POST /blend Blend multiple personas. ```json { "personas": [ {"KonradFreeman": 0.7}, {"Daniel": 0.3} ] } ``` ### GET /personas List all cached personas. ### GET /persona/{author} Get a specific persona's JSON. ### POST /batch-extract Extract personas for all authors in the bank. ## Usage Examples ### Python Client ```python from deerflow_persona_query import PersonaQueryEngine from ollama import chat def ollama_llm(prompt, system=""): response = chat( model="llama3.2", messages=[ {"role": "system", "content": system}, {"role": "user", "content": prompt} ] ) return response["message"]["content"] # Initialize engine = PersonaQueryEngine( bank_path="/mnt/user-data/uploads/bank", llm_callable=ollama_llm, cache_path="/mnt/user-data/workspace/personas" ) # Query in a persona's voice result = engine.query( "What do you think about RAG?", persona="KonradFreeman" ) print(result.content) # Blend personas result = engine.query( "Should I use local LLMs or cloud APIs?", blended_persona=[("KonradFreeman", 0.6), ("Daniel", 0.4)] ) print(result.content) # Extract all personas engine.extract_all_personas() ``` ## Persona Schema Each persona contains: ```json { "name": "KonradFreeman", "author": "KonradFreeman", "tone": "analytical, skeptical, conversational", "vocabulary_level": "technical", "sentence_structure": "varied with short punchy sentences", "psychological_traits": ["curious", "skeptical", "pragmatic"], "common_themes": ["AI", "local-first", "RAG", "Ollama"], "references": ["Ollama", "LangChain", "Konrad"], "anti_patterns": ["corporate speak", "over-explaining"], "formality_score": 0.4, "humor_score": 0.6, "technical_depth": 0.8, "emotional_warmth": 0.5, "reasoning_style": "iterative, builds from small pieces", "source_documents": ["mdzvfl6", "..."] } ``` ## Configuration Environment variables: - `BANK_PATH`: Path to DeerFlow bank (default: `/mnt/user-data/uploads/bank`) - `PERSONA_CACHE`: Path to cache personas (default: `/mnt/user-data/workspace/personas`) - `OLLAMA_MODEL`: Ollama model to use (default: `llama3.2`) ## Next Steps 1. **Extract all personas** from your bank: ```bash curl -X POST http://localhost:8000/batch-extract ``` 2. **Test queries** in different voices: - KonradFreeman (technical, skeptical) - Your own voice - Blend them 3. **Rebuild UI** in Next.js + shadcn for production 4. **Add RLHF loop**: Let users rate outputs, adjust persona weights automatically 5. **Integrate with your existing chat app**: Use this as the style engine backend ## How It Works 1. **Persona Extraction**: LLM analyzes documents by an author, outputs structured JSON describing their voice 2. **Persona Blending**: Weighted combination of multiple personas, normalizing scores and deduplicating traits 3. **Style Application**: Retrieved documents are summarized/rewritten using the persona's JSON as a system prompt 4. **Caching**: Extracted personas are cached as JSON files for fast retrieval ## Files - `personagen_engine.py`: Core Persona dataclass, Extractor, Blender, StyleEngine - `deerflow_persona_query.py`: DeerFlow bank interface, query engine - `persona_api.py`: FastAPI server - `persona_ui.py`: Streamlit UI (prototype) ## License MIT - Build on it, break it, make it yours.
# DeerFlow Persona Query Engine Turn your document bank into a voice-driven intelligence system. Query your data and get answers in any author’s voice or blend multiple personas into something entirely new. Built on Daniel’s 4,865-document DeerFlow corpus. ## Architecture ``` ┌─────────────────────────────────────────────────────────────┐ │ Persona Query Engine │ ├─────────────────────────────────────────────────────────────┤ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ FastAPI │ │ Streamlit │ │ Python Client │ │ │ │ Server │ │ Interface │ │ │ │ │ └──────┬───────┘ └──────────────┘ └──────────────────┘ │ │ │ │ │ ┌──────▼───────┐ │ │ │ Query │ │ │ │ Engine │ │ │ └──────┬───────┘ │ │ │ │ │ ┌──────▼─────────────────────────────────┐ │ │ │ DeerFlow Bank (4,865 docs) │ │ │ │ - documents/ │ │ │ │ - metadata/index.json │ │ │ │ - vectors/ │ │ │ └────────────────────────────────────────┘ │ │ │ │ │ ┌──────▼───────┐ ┌──────────────┐ ┌──────────────────┐ │ │ │ Persona │ │ Persona │ │ Style │ │ │ │ Extractor │ │ Blender │ │ Engine │ │ │ └──────────────┘ └──────────────┘ └──────────────────┘ │ │ │ │ │ ┌──────▼───────┐ │ │ │ Ollama │ (llama3.2 / gemma-3) │ │ └──────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` ## Quick Start ### 1. Install dependencies ```bash pip install fastapi uvicorn ollama streamlit requests pydantic ``` ### 2. Launch the API ```bash python persona_api.py ``` Runs on `http://localhost:8000` ### 3. Launch the UI (optional) ```bash streamlit run persona_ui.py ``` Runs on `http://localhost:8501` ### 4. Query the system ```bash # Single persona curl -X POST http://localhost:8000/query \ -H "Content-Type: application/json" \ -d '{ "query": "What do you think about local-first AI?", "persona": "KonradFreeman" }' # Blended personas curl -X POST http://localhost:8000/query \ -H "Content-Type: application/json" \ -d '{ "query": "How should I approach building an AI startup?", "blended_persona": [ {"KonradFreeman": 0.7}, {"Daniel": 0.3} ] }' ``` ## API ### POST `/query` Run a query with persona styling. **Request** ```json { "query": "string", "persona": "optional string", "blended_persona": [{"author": weight}], "search_mode": "hybrid | keyword | author" } ``` **Response** ```json { "success": true, "query": "original query", "persona_used": "KonradFreeman", "documents_found": 12, "content": "styled response", "source_documents": ["id1", "id2"], "persona_json": {} } ``` --- ### POST `/extract` Generate a persona profile from an author’s documents. ```json { "author": "KonradFreeman" } ``` ### POST `/blend` Combine multiple personas into a weighted composite. ```json { "personas": [ {"KonradFreeman": 0.7}, {"Daniel": 0.3} ] } ``` ### GET `/personas` List cached personas. ### GET `/persona/{author}` Retrieve a persona JSON. ### POST `/batch-extract` Extract personas for the entire corpus. --- ## Python Client ```python from deerflow_persona_query import PersonaQueryEngine from ollama import chat def ollama_llm(prompt, system=""): response = chat( model="llama3.2", messages=[ {"role": "system", "content": system}, {"role": "user", "content": prompt} ] ) return response["message"]["content"] engine = PersonaQueryEngine( bank_path="/mnt/user-data/uploads/bank", llm_callable=ollama_llm, cache_path="/mnt/user-data/workspace/personas" ) # Single persona result = engine.query( "What do you think about RAG?", persona="KonradFreeman" ) print(result.content) # Blended personas result = engine.query( "Local LLMs vs cloud APIs?", blended_persona=[("KonradFreeman", 0.6), ("Daniel", 0.4)] ) print(result.content) # Extract all personas engine.extract_all_personas() ``` ## Persona Schema Each persona is a structured representation of voice and thinking patterns: ```json { "name": "KonradFreeman", "author": "KonradFreeman", "tone": "analytical, skeptical, conversational", "vocabulary_level": "technical", "sentence_structure": "short, punchy, varied", "psychological_traits": ["curious", "skeptical", "pragmatic"], "common_themes": ["AI", "local-first", "RAG", "Ollama"], "references": ["Ollama", "LangChain"], "anti_patterns": ["corporate speak", "over-explaining"], "formality_score": 0.4, "humor_score": 0.6, "technical_depth": 0.8, "emotional_warmth": 0.5, "reasoning_style": "iterative, builds from primitives", "source_documents": ["mdzvfl6"] } ``` ## Configuration Environment variables: - `BANK_PATH` → document store (default: `/mnt/user-data/uploads/bank`) - `PERSONA_CACHE` → persona cache (default: `/mnt/user-data/workspace/personas`) - `OLLAMA_MODEL` → model selection (default: `llama3.2`) ## Roadmap - Extract personas across the full corpus - Stress test voice consistency across queries - Replace Streamlit with Next.js + shadcn UI - Add feedback loop for dynamic persona tuning - Plug into existing chat systems as a style backend ## How It Works Persona extraction converts raw writing into structured voice profiles. Blending merges multiple profiles into weighted hybrids. The engine retrieves relevant documents, then rewrites or summarizes them through the selected persona lens. Extracted personas are cached for speed, turning style into a reusable primitive. ## Project Structure - `personagen_engine.py` → core logic (extractor, blender, style engine) - `deerflow_persona_query.py` → query interface - `persona_api.py` → FastAPI server - `persona_ui.py` → Streamlit prototype ## License MIT. Use it, modify it, break it, rebuild it.
gpt-5-3