Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,298 changes: 1,298 additions & 0 deletions DESIGN.md

Large diffs are not rendered by default.

946 changes: 946 additions & 0 deletions REQ.md

Large diffs are not rendered by default.

1,577 changes: 1,577 additions & 0 deletions SPEC.md

Large diffs are not rendered by default.

490 changes: 490 additions & 0 deletions spec.md

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions test_langsmith.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from langchain_openai import ChatOpenAI
import os
from dotenv import load_dotenv

# Load environment variables from .env file
load_dotenv()

# Debug print to confirm the key is being loaded
print("OPENAI KEY LOADED:", os.getenv("OPENAI_API_KEY")[:10], "...")

# Initialize the OpenAI LLM
llm = ChatOpenAI()

# Send a basic test message
response = llm.invoke("Hello, world!")

# Output the response
print("LLM RESPONSE:", response)
73 changes: 73 additions & 0 deletions voicedform_graph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from dotenv import load_dotenv
import os
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, END
from langchain_core.runnables import RunnableLambda

# ✅ Load environment
load_dotenv()

# ✅ DEBUG print to confirm key is loaded
print("OPENAI_KEY LOADED:", os.getenv("OPENAI_API_KEY")[:10], "...")
print("LangSmith project:", os.getenv("LANGSMITH_PROJECT"))

# ✅ Reusable LLM
llm = ChatOpenAI(model="gpt-4", temperature=0)

# 🧠 Node: Supervisor (decides flow, stubbed for now)
def supervisor_node(state: dict) -> dict:
print("🧭 Supervisor: Deciding flow...")
return {"form_type": "accident_report"}

# 🧠 Node: Form Selector (uses LLM to describe form)
def form_selector_node(state: dict) -> dict:
form_type = state.get("form_type", "unknown")
print(f"📄 Form Selector: Received form type → {form_type}")
message = f"You are helping complete a form of type: {form_type}. What's the first field?"
response = llm.invoke(message)
return {"form_type": form_type, "first_field": response.content}

# 🧠 Node: Form Completion (mock interaction)
def form_completion_node(state: dict) -> dict:
print(f"✍️ Form Completion: Starting with → {state.get('first_field')}")
response = llm.invoke("Let's pretend to fill out this form together.")
return {"form_complete": response.content}

# 🧠 Node: Validator (trivial check for now)
def validator_node(state: dict) -> dict:
print("✅ Validator: Verifying...")
is_valid = "form_complete" in state
return {"valid": is_valid}

# ✅ Build the LangGraph DAG
from typing import TypedDict, Optional

class GraphState(TypedDict, total=False):
input: Optional[str]
form_type: Optional[str]
first_field: Optional[str]
form_complete: Optional[str]
valid: Optional[bool]

graph = StateGraph(GraphState)


graph.add_node("supervisor", RunnableLambda(supervisor_node))
graph.add_node("form_selector", RunnableLambda(form_selector_node))
graph.add_node("form_completion", RunnableLambda(form_completion_node))
graph.add_node("validator", RunnableLambda(validator_node))

# ⛓️ Wire nodes together
graph.set_entry_point("supervisor")
graph.add_edge("supervisor", "form_selector")
graph.add_edge("form_selector", "form_completion")
graph.add_edge("form_completion", "validator")
graph.add_edge("validator", END)

# ✅ Compile and Run
dag = graph.compile()

# 🧪 Invoke with empty state
print("\n🧪 Running VoicedForm DAG...\n")
output = dag.invoke({})
print("\n🎉 Final output:", output)
22 changes: 22 additions & 0 deletions web/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Supabase
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=

# NextAuth
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=

# Google OAuth
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

# OpenAI
OPENAI_API_KEY=

# Whisper Service
WHISPER_WS_URL=ws://localhost:8765

# Gmail API
GMAIL_CLIENT_ID=
GMAIL_CLIENT_SECRET=
41 changes: 41 additions & 0 deletions web/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
8 changes: 8 additions & 0 deletions web/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"printWidth": 80,
"arrowParens": "always"
}
Loading